Programmera nätverk och trådar c#

Permalänk
Medlem

Programmera nätverk och trådar c#

Jag har för ett tag sen fått för mig att lära mig programmera lite, och är då framför allt intresserad av spelprogrammering.
så för o förenkla för mig själv så valde jag c# och XNA, vilket då har gett mig ganska grundläggande programmeringskunskaper och vad gäller just XNA så är det ju ganska lätt och jag klarat av o skriva ett halvt fungerande spel.
men nu är det dags o förnya det här projektet och skriva om det från början med framförallt ett tillägg av nätverk och möjligtvis användade av trådar.
Har googleat lite hit o dit om ämnet men förstår ändå inte riktigt så hoppades att någon vänlig själ kunde förklara lite för mig!

1. För det första så undrar jag då, HUR fungerar dessa trådar i koden får ingen direkt förklaring på det. som jag har förstått det så går väl programmet uppifrån och ner i koden? Vad händer då om jag gör en loop i stil med detta inuti min main tråd:
for (int i = 0; i < 2; i++)
{
Thread t = new Thread(new ThreadStart(Service));
t.Start();
}
som jag ser det så kommer antingen maintråden fortsätta, eller kommer den vänta på dessa två trådar?

2. Vad gäller nätverk med så är jag inne på att börja med TCP om ingen anser att UDP skulle va ett bättre val?

3. Jag undrar dessutom lite mer exakt VAD är en networkstream, alltså hur ska mitt program förstå vad som är vad utav det som skickas?
tänk typ att jag vill att server ska få en int variabel av clienten, och så kanske även en string, måste jag skicka det här varsin gång, och när jag nu gör det, hur vet server/clienten vad som är vad?

tacksam för svar!

Permalänk
Medlem

Kolla in lidgren network som är ett bibliotek för dotnet https://code.google.com/p/lidgren-network-gen3/

Skickades från m.sweclockers.com

Permalänk
Skrivet av xedoz1:

Jag har för ett tag sen fått för mig att lära mig programmera lite, och är då framför allt intresserad av spelprogrammering.
så för o förenkla för mig själv så valde jag c# och XNA, vilket då har gett mig ganska grundläggande programmeringskunskaper och vad gäller just XNA så är det ju ganska lätt och jag klarat av o skriva ett halvt fungerande spel.
men nu är det dags o förnya det här projektet och skriva om det från början med framförallt ett tillägg av nätverk och möjligtvis användade av trådar.
Har googleat lite hit o dit om ämnet men förstår ändå inte riktigt så hoppades att någon vänlig själ kunde förklara lite för mig!

1. För det första så undrar jag då, HUR fungerar dessa trådar i koden får ingen direkt förklaring på det. som jag har förstått det så går väl programmet uppifrån och ner i koden? Vad händer då om jag gör en loop i stil med detta inuti min main tråd:
for (int i = 0; i < 2; i++)
{
Thread t = new Thread(new ThreadStart(Service));
t.Start();
}
som jag ser det så kommer antingen maintråden fortsätta, eller kommer den vänta på dessa två trådar?

2. Vad gäller nätverk med så är jag inne på att börja med TCP om ingen anser att UDP skulle va ett bättre val?

3. Jag undrar dessutom lite mer exakt VAD är en networkstream, alltså hur ska mitt program förstå vad som är vad utav det som skickas?
tänk typ att jag vill att server ska få en int variabel av clienten, och så kanske även en string, måste jag skicka det här varsin gång, och när jag nu gör det, hur vet server/clienten vad som är vad?

tacksam för svar!

1.
De trådar du skapar kommer att exekvera "parallellt" med din main-tråd. "Parallellt" innebär nte nödvändigtvis att de exekverar samtidigt, det beror ev. Hur det ser ut med tillgängliga processorkärnor osv. Du kan se det som att det körs samtidigt men du kan aldrig vara säker på hur varje tråd blir tilldelad processortid. Det här gör att det i många fall blir nödvändogt att synkronisera trådar, se http://msdn.microsoft.com/en-us/library/ms173179.aspx.

Vad som händer med dina skapade trådar om main-tråden når sitt slut beror på huruvida dina trådar satts upp som bakgrundstrådar eller inte, vill jag minnas.

2.
Jag ser det så här: om det är information man behöver vara säker på att den kommer fram till mottagaren oavsett hur lång tid det tar så gäller TCP (man lär får reda på om ett datapaket inte kommer fram, t.ex. Om det blir timeout på länken). UDP lämpar sig väl för realtidsinformation som har ett "bäst-före-datum", t.ex. audiostreaming där det kanske kan vara bättre att bara strunta i om det försvinner några millisekunder då och då, det kanske är viktigare att komma vidare i strömmen. UDP är lite grann "fire-and-forget", avsändaren får inte reda på att mottagaren tagit emot datapaketen. Det finns dock inget hinder för att själv implementera övervakning av kommunikationen på en högre nivå (t.ex. att mottagaren via UDP skickar en någon form av meddelande där den bekräftar att meddelandet mottagits).

3.
Jag föreslår att du tittar lite på serialisering av objekt, t.ex. den här tråden som jag gissar liknar det du är ute efter (någon form av egendefinierat objekt skickas via TCP:
http://stackoverflow.com/questions/7849074/serializing-object...

Ett tips är att skaffa en bra bok att läsa, jag tror att jag hade "Professional C# 2008" av bl.a. Christian Nagel och jag tyckte den var rätt OK. Om du vill använda de grejer som tillkommit i de senaste .NET-versionerna behöver du dock en nyare bok.

Permalänk
Medlem
Skrivet av xedoz1:

Jag har för ett tag sen fått för mig att lära mig programmera lite, och är då framför allt intresserad av spelprogrammering.
så för o förenkla för mig själv så valde jag c# och XNA, vilket då har gett mig ganska grundläggande programmeringskunskaper och vad gäller just XNA så är det ju ganska lätt och jag klarat av o skriva ett halvt fungerande spel.
men nu är det dags o förnya det här projektet och skriva om det från början med framförallt ett tillägg av nätverk och möjligtvis användade av trådar.
Har googleat lite hit o dit om ämnet men förstår ändå inte riktigt så hoppades att någon vänlig själ kunde förklara lite för mig!

1. För det första så undrar jag då, HUR fungerar dessa trådar i koden får ingen direkt förklaring på det. som jag har förstått det så går väl programmet uppifrån och ner i koden? Vad händer då om jag gör en loop i stil med detta inuti min main tråd:
for (int i = 0; i < 2; i++)
{
Thread t = new Thread(new ThreadStart(Service));
t.Start();
}
som jag ser det så kommer antingen maintråden fortsätta, eller kommer den vänta på dessa två trådar?

tacksam för svar!

Programmet går som vanligt uppåfrån och ner. Skillnaden på att kalla på en funktion eller en funktion som en tråd är att i fallet med tråden väntar inte main på att funktionen ska köras färdigt, som ett normalt funktionsanrop annars gör.

Du får helt enkelt se en ny tråd som ett nytt program, ungefär som att du hade startat ett till program, fast med en annan funktion istället för main.

Säker på att du ska börja använda trådar? Det är inte helt enkelt, speciellt om trådarna behöver kommunicera med varandra.

Permalänk
Medlem
Skrivet av kobb3:

Programmet går som vanligt uppåfrån och ner. Skillnaden på att kalla på en funktion eller en funktion som en tråd är att i fallet med tråden väntar inte main på att funktionen ska köras färdigt, som ett normalt funktionsanrop annars gör.

Du får helt enkelt se en ny tråd som ett nytt program, ungefär som att du hade startat ett till program, fast med en annan funktion istället för main.

Säker på att du ska börja använda trådar? Det är inte helt enkelt, speciellt om trådarna behöver kommunicera med varandra.

lite som jag antog det då.
om jag inte har förstått det snett så kommer jag behöva ha trådar om jag ska ha flera clienter på samma function. och dessutom kommer trådarna kunna komma till nytta för annat speciellt vad gäller servern då.

Permalänk
Medlem
Skrivet av xedoz1:

lite som jag antog det då.
om jag inte har förstått det snett så kommer jag behöva ha trådar om jag ska ha flera clienter på samma function. och dessutom kommer trådarna kunna komma till nytta för annat speciellt vad gäller servern då.

Mja, behöva är ett starkt ord. Det beror på hur du kör allting, dvs ska alla klienter vara på samma dator eller på olika datorer? Ska de vara på olika datorer behöver du generellt inte ha trådar.

Att ha servern på en separat tråd låter dock som en bra idé, det svåraste kommer dock vara kommunikationen (över nätverk) och jag föreslår du börjar med det

Permalänk
Medlem
Skrivet av arcticslayer:

1.
De trådar du skapar kommer att exekvera "parallellt" med din main-tråd. "Parallellt" innebär nte nödvändigtvis att de exekverar samtidigt, det beror ev. Hur det ser ut med tillgängliga processorkärnor osv. Du kan se det som att det körs samtidigt men du kan aldrig vara säker på hur varje tråd blir tilldelad processortid. Det här gör att det i många fall blir nödvändogt att synkronisera trådar, se http://msdn.microsoft.com/en-us/library/ms173179.aspx.

Vad som händer med dina skapade trådar om main-tråden når sitt slut beror på huruvida dina trådar satts upp som bakgrundstrådar eller inte, vill jag minnas.

2.
Jag ser det så här: om det är information man behöver vara säker på att den kommer fram till mottagaren oavsett hur lång tid det tar så gäller TCP (man lär får reda på om ett datapaket inte kommer fram, t.ex. Om det blir timeout på länken). UDP lämpar sig väl för realtidsinformation som har ett "bäst-före-datum", t.ex. audiostreaming där det kanske kan vara bättre att bara strunta i om det försvinner några millisekunder då och då, det kanske är viktigare att komma vidare i strömmen. UDP är lite grann "fire-and-forget", avsändaren får inte reda på att mottagaren tagit emot datapaketen. Det finns dock inget hinder för att själv implementera övervakning av kommunikationen på en högre nivå (t.ex. att mottagaren via UDP skickar en någon form av meddelande där den bekräftar att meddelandet mottagits).

3.
Jag föreslår att du tittar lite på serialisering av objekt, t.ex. den här tråden som jag gissar liknar det du är ute efter (någon form av egendefinierat objekt skickas via TCP:
http://stackoverflow.com/questions/7849074/serializing-object...

Ett tips är att skaffa en bra bok att läsa, jag tror att jag hade "Professional C# 2008" av bl.a. Christian Nagel och jag tyckte den var rätt OK. Om du vill använda de grejer som tillkommit i de senaste .NET-versionerna behöver du dock en nyare bok.

jo har övervägt bok, föredrar dock läsning på nätet då jag av nån anledning har otroligt svårt för att hålla koncentrationen med fysiska böcker.
men det med serialisering ger mig bara mer frågor egentligen, alltså mer exakt så undrar jag nog över detta:
House house = DeserializeFromXml<House>(encoder.GetString(message, 0, bytesRead));

för att min kod ska förstå att det är ett hus så måste jag för skriva i koden "det här är ett hus, läs av huset"
hur ska jag kunna skicka tex, spelar position, spelar health, spelar damage och dessamma gällande tex från servern kommer mobs med samma info.
hur ska clienterna / servern veta vad som är vad?
blir det en otroligt lång if sats som frågar efter allt och if blabla gör så och så?
ska jag ta all info jag vill skicka o lägga i ett o samma "paket" och skicka emellan. vad händer om min server behöver skicka info om 25mobs på en karta och 30 mobs på en annan karta?

jag tänker något i stil med server: "foreach mob på samma karta som spelaren" "skicka information"
client: "ta emot info ifrån servern, här är det visst en mob oxå"
man måste väl på något sätt tolka strömmen, jag jämför lite snabbt med när jag läser XML nu så gör jag nåt i stil med att jag letar efter tex "name" i xml filen, sen i koden så vet jag att inuti name tagen finns infon jag behöver så när jag hittat name så skriver jag dess value i variabeln name typ.
är det något i stil med detta jag ska göra med min networkstream också?

Skrivet av kobb3:

Mja, behöva är ett starkt ord. Det beror på hur du kör allting, dvs ska alla klienter vara på samma dator eller på olika datorer? Ska de vara på olika datorer behöver du generellt inte ha trådar.

Att ha servern på en separat tråd låter dock som en bra idé, det svåraste kommer dock vara kommunikationen (över nätverk) och jag föreslår du börjar med det

så vitt jag förstod det måste man ju ha en tcp listener för varje client, och det bör väl va bäst o köras trådat så man får det att updatera sig så nära på samtidigt som möjligt.

Permalänk
Medlem

Kan absolut inget om spelprogrammering men du kan använda WCF för "icke kritiska" anrop mellan clienter och server. Några exempel kan ju vara authenciering, spelarinfo om spelaren, namn, svårighetsgrader etc. Det var det jag kunde komma på för tillfället.

Permalänk
Hedersmedlem
Skrivet av xedoz1:

ska jag ta all info jag vill skicka o lägga i ett o samma "paket" och skicka emellan. vad händer om min server behöver skicka info om 25mobs på en karta och 30 mobs på en annan karta?

Ett vanligt sätt är att först skicka något (gärna med känd storlek) som talar om vad man tänker skicka (och kanske till och med hur många) och sedan själva informationen. Kanske kan du skicka
0 <objekt1> 0 <objekt2> ... 0 <objekt25>
eller
0 25 <objekt1> <objekt2> .. <objekt25>
där 0 anger objekttypen.

Permalänk
Inaktiv

Bygg gärna efter konceptet MVC, Model, View, Control.

I ditt spel så kommer view vara det som användaren ser. View kommer hämta data från model när data uppdateras, 60 gånger per sekund eller vad du ny bedömer är bäst.

Model kommer sköta all logik, hålla koll på att rätt saker rör rätt variabler etc. Model bör även hålla koll på att olika trådar inte modifierar samma variabler, synchronized, atomic eller vad man nu vill kalla det.

Control kommer påverka view, hämta data från nätverket, ta emot knapptryck och skriva data till nätverket.

-- Med detta i åtanke --
Det vill nog finnas en tråd i control som hämtar anrop från internet och lägger in dem i modellen på ett snyggt sätt. Samma tråd skulle kunna skriva data från modellen till internet. Det bör även finna en tråd, eller listener som tar emot knapptryck från användaren och skriver detta till modellen.

View borde ha en tråd som hämtar data från modellen med jämna intervall.

Permalänk
Skrivet av xedoz1:

jo har övervägt bok, föredrar dock läsning på nätet då jag av nån anledning har otroligt svårt för att hålla koncentrationen med fysiska böcker.
men det med serialisering ger mig bara mer frågor egentligen, alltså mer exakt så undrar jag nog över detta:
House house = DeserializeFromXml<House>(encoder.GetString(message, 0, bytesRead));

för att min kod ska förstå att det är ett hus så måste jag för skriva i koden "det här är ett hus, läs av huset"
hur ska jag kunna skicka tex, spelar position, spelar health, spelar damage och dessamma gällande tex från servern kommer mobs med samma info.
hur ska clienterna / servern veta vad som är vad?
blir det en otroligt lång if sats som frågar efter allt och if blabla gör så och så?
ska jag ta all info jag vill skicka o lägga i ett o samma "paket" och skicka emellan. vad händer om min server behöver skicka info om 25mobs på en karta och 30 mobs på en annan karta?

jag tänker något i stil med server: "foreach mob på samma karta som spelaren" "skicka information"
client: "ta emot info ifrån servern, här är det visst en mob oxå"
man måste väl på något sätt tolka strömmen, jag jämför lite snabbt med när jag läser XML nu så gör jag nåt i stil med att jag letar efter tex "name" i xml filen, sen i koden så vet jag att inuti name tagen finns infon jag behöver så när jag hittat name så skriver jag dess value i variabeln name typ.
är det något i stil med detta jag ska göra med min networkstream också?

så vitt jag förstod det måste man ju ha en tcp listener för varje client, och det bör väl va bäst o köras trådat så man får det att updatera sig så nära på samtidigt som möjligt.

Du kan serialisera (på sändsidan) och deserialisera (på mottagarsidan) vilket egendefinierat objekt som helst så länge applikationerna på båda sidor av applikationen vet hur objektet är definierat och att serialisering/deserialiseringen är rätt specad. Läs på lite mer om det där så inser du att det är lättare än den hantering av XML du gjort.

Vad gäller TCP listener så har jag för iag att man har en sådan på servern och för varje inkommande connection kickar man igång en ny tråd där själva kommunikationen sker, eller nåt åt det hållet. Du vill antagligen bara ha en port som klienterna ansluter till och då blir det en listener.

Själv tycker jag en bok är väldigt bra, man kan ha den vid sidan om och inte behöva växla till webläsare och eta varje gång man undrar över något. En bra bok har ofta väl utvecklade exempel som hänger ihop.

Permalänk
Datavetare

Varför ska du överhuvudtaget blanda in trådar? Att använda trådar komplicerar programmet rätt mycket och i ditt fall kommer en multicore CPU inte användas på något konstruktivt sätt då din nätverkstrafik kommer vara väldigt sparsam och inte alls belasta den CPU-tråd den körs på.

Du kommer däremot vara tvungen att ha logik för att på ett korrekt sätt få över din nätverksdata till huvudtråden, något som är svårt att göra både korrekt och effektivt (lätt att göra en av dessa).

I C#/.Net finns något som kallas "asynchronous calls" (dels detta och dels det nya async/await i C#5), varför inte använda det för att utföra nätverksfunktionerna i "bakgrunden" utan att blanda in flera trådar? Kommer antagligen bli mer effektivt än att använda flera trådar i detta fall och du slipper problematiken med att transportera information mellan trådar.

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem

Om du vill lära dig tråd hantering och C# så rekommenderar jag denna läsning http://www.albahari.com/threading/ en bit ur en stor bok jag också kan grymt rekommendera om du vill fördjupa dig i C# med namnet C# in a nutshell

Visa signatur

Speldator: Ryzen 7800X3D, 64GB DDR5, RTX 5090
Server: i7-8700k, 32GB DDR4, RTX2080
Steam deck, Rog Ally + de fiesta konsoler.

Permalänk
Skrivet av MugiMugi:

Om du vill lära dig tråd hantering och C# så rekommenderar jag denna läsning http://www.albahari.com/threading/ en bit ur en stor bok jag också kan grymt rekommendera om du vill fördjupa dig i C# med namnet C# in a nutshell

+1 på den länken, den hade jag stor nytta av när jag skulle komma igång med trådar.

Permalänk
Medlem

Nu när jag började utveckla en sorts livssimulator (Jo... I c# Forms..) så hängde sig ofta GUIn när ett visst antal år hade passerat.
Funderade också på trådar, men det verkade väldigt komplicerat, så testade jag istället backgroundworkers, vilket fungerade hur bra som helst!

Lägg in alla metoder i backgroundworker_DoWork
och sedan starta workern (ASync... något) under en knapp eller vad du nu önskar

Och för att ändra GUI controls från en annan tråd (Tex funktion som körs på backgroundworkern) skriv
"control.Invoke(new action(() => {control.text = "text"}));

Kan dock inte uttala mig om vad som fungerar bäst, att skapa nya trådar eller att använda backgroundworker.

Permalänk
Avstängd

Det är exakt noll skillnad på en Bakgrundstråd och en Background worker. Dock ska man inte använda trådklassen direkt så en Backgroiundworker eller ThreadPool är bättre.

edit: En Bakgrundstråd är en helt vanlig tråd konfad att dö om huvudprocessen dör

Visa signatur
Permalänk
Medlem

tack för input.
detta har jag nu kommit fram till:
Jag kommer göra en server tråd som läser av en network stream, och jag ska göra en class "paket" som kommer innehålla id(för att jag ska veta vad det är för paket) och ett värde. kommer skicka dessa paket på streamen och de kommer då få en längd och värde, som servern då läser av och lägger i en volatile lista med paket, som huvudtråden sedan kommer uppdatera ifrån.
clienten kommer göra det samma med paketen han får ifrån servern.

synpunkter, åsikter?

Permalänk
Medlem
Skrivet av xedoz1:

tack för input.
detta har jag nu kommit fram till:
Jag kommer göra en server tråd som läser av en network stream, och jag ska göra en class "paket" som kommer innehålla id(för att jag ska veta vad det är för paket) och ett värde. kommer skicka dessa paket på streamen och de kommer då få en längd och värde, som servern då läser av och lägger i en volatile lista med paket, som huvudtråden sedan kommer uppdatera ifrån.
clienten kommer göra det samma med paketen han får ifrån servern.

synpunkter, åsikter?

Hur viktigt är id? Blir det alldeles fel om du bara ger varje inkommetpaket ett id?

Permalänk
Medlem
Skrivet av kobb3:

Hur viktigt är id? Blir det alldeles fel om du bara ger varje inkommetpaket ett id?

jag kommer skicka många olika typer av paket, tänk tex, unit, event, action, så måste veta vad det är för typ av paket. det är vad idt kommer va till.

Permalänk
Datavetare

Är du helt på det klara med vad en volatile deklaration betyder i C#? Och hur har du tänkt använda/implementera din lista så den är korrekt? Är just de här bitarna som är väldigt luriga att få till på ett både korrekt och effektivt sätt, var därför jag föreslog att du kanske ska skippa trådar helt (då jag antar att mängden data inte är så stor) och i stället använda non-blocking I/O.

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Medlem
Skrivet av Yoshman:

Är du helt på det klara med vad en volatile deklaration betyder i C#? Och hur har du tänkt använda/implementera din lista så den är korrekt? Är just de här bitarna som är väldigt luriga att få till på ett både korrekt och effektivt sätt, var därför jag föreslog att du kanske ska skippa trådar helt (då jag antar att mängden data inte är så stor) och i stället använda non-blocking I/O.

nej det är de jag inte är bara att det gör det möjligt att ändra ifrån andra trådar, och jag försöker lära mig genom att testa sakerna. men såg andra föreslå med att en volatile är ett sätt att få trådarna att kommunicera med varandra, och detta testades bara med en int för att se hur det fungerar.
det KAN vara ganska "mycke" data som går igenom, vet ju inte vart det slutar när det väl är klart och tanken är att ha fler än 1 client med och de guider jag sett där det gäller flera clienter på TCP oftast innebär trådar.

det senaste problemet jag stötte på rent teoretiskt va att jag ska loopa / tömma en lista med grejer som hela tiden får nytt, och detta i min maintråd. och det är vad jag försöker komma på en lösning på just nu.

har inte skrivit speciellt mycke på det än heller då jag sitter o skriver ett teoretiskt schema för vad som ska hända i koden.

Permalänk
Medlem

vill man göra det lätt för sig, så kan man använda någon av de Thread-Safe Collections som finns.
det är kanske mer effektivt att själv skriva trådsäker lagring av inkommande paket, men att bara putta in dem i en ConcurrentQueue<T> kan ju iaf vara en början.

Visa signatur

as far as we can tell, the massacre went well...

Permalänk
Avstängd
Skrivet av Yoshman:

Är du helt på det klara med vad en volatile deklaration betyder i C#? Och hur har du tänkt använda/implementera din lista så den är korrekt? Är just de här bitarna som är väldigt luriga att få till på ett både korrekt och effektivt sätt, var därför jag föreslog att du kanske ska skippa trådar helt (då jag antar att mängden data inte är så stor) och i stället använda non-blocking I/O.

Non blocking IO är bra, men ibland kan maintråden vara för seg för input, tex om man vill göra beräkningar som olika filter eller interpolation. Men i detta fall så lär det bara vara att köra på!

Visa signatur
Permalänk
Datavetare
Skrivet av jovnas:

vill man göra det lätt för sig, så kan man använda någon av de Thread-Safe Collections som finns.
det är kanske mer effektivt att själv skriva trådsäker lagring av inkommande paket, men att bara putta in dem i en ConcurrentQueue<T> kan ju iaf vara en början.

Problemet med alla generella saker som "ConcurrentX" är att de i princip alltid bara kan säkerställa att de är korrekta. Men i detta fall låter det trots allt som det är den rimligaste vägen fram.

Kör man Microsofts eget exempel på "ConcurrentQueue" så får man överlägset bäst prestanda om man använder en CPU-tråd, ju fler trådar man använder ju långsammare gick det... Vad är poängen då? Faktum är att ConcurrentQueue inte var speciellt mycket snabbare än den enormt naiva implementation jag gjorde i BadCustom() i detta test

using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; class Program { const int NUM_ELEM = 10000000; class Node { Node next; long value; public Node(long v, Node n) { value = v; next = n; } public long Value { get { return value; } } public Node Next { get { return next; } } } static Action BadCustom() { Node root = null; for (var i = 0; i < NUM_ELEM; i++) root = new Node(i, root); long outerSum = 0; Action action = () => { long localSum = 0; for (; ; ) { Node first = root; if (first == null) break; Node second = first.Next; if (Interlocked.CompareExchange(ref root, second, first) == first) localSum += first.Value; } Interlocked.Add(ref outerSum, localSum); }; return () => Parallel.Invoke(action, action); } static Action GoodCustom() { Node root = null; for (var i = 0; i < NUM_ELEM; i++) root = new Node(i, root); long outerSum = 0; Action action = () => { long localSum = 0; Node n = Interlocked.Exchange(ref root, null); while (n != null) { localSum += n.Value; n = n.Next; } Interlocked.Add(ref outerSum, localSum); }; return () => Parallel.Invoke(action, action); } static Action Standard() { var cq = new ConcurrentQueue<long>(); for (var i = 0; i < NUM_ELEM; i++) cq.Enqueue(i); long outerSum = 0; Action action = () => { long localSum = 0; long localValue; while (cq.TryDequeue(out localValue)) localSum += localValue; Interlocked.Add(ref outerSum, localSum); }; return () => Parallel.Invoke(action, action); } static void Measure(Action action, String desc) { var start = DateTime.Now; action(); var end = DateTime.Now; Console.WriteLine("Running '{0}' took {1}", desc, end - start); } static void Main() { Measure(GoodCustom(), "Does not really use parallelism"); Measure(BadCustom(), "Too much contention"); Measure(Standard(), "Standard implementation"); Console.ReadKey(); } }

Dold text

GoodCustom() var 5x snabbare i detta fall (använde två trådar) än ConcurrentQueue.

För att få saker att bli effektivt över flera trådar måste man göra all form av kommunikation mellan trådarna så sällan det bara går. Visst går det att använda en kö, men då ska den ha ett gränssnitt som låter en köa och plocka ut många element i en smäll. I detta fall med spelet bör man nog plocka av alla paket som är köade från nätverkstråden, spara dem temporärt på stacken eller likande medan man betar av dem en efter en.

Men i detta fall är nog det mest effektiva allt helt undvika trådar. Även om huvudtråden gör en del tunga beräkningar spelar ju det ingen roll för I/O då dessa operationer köas i OS:et under tiden, när man väl sedan gör sin non-blocking I/O får man bara upp ett gäng paket om senaste varvet runt i spel-loopen tog en del tid, men det ökar ju bara effektiviteten tack vare att de leder till bättre cache-lokalitet

Visa signatur

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Permalänk
Avstängd

Jag håller helt med dig, vill bara upplysa att hastigheten man pollar kan spela roll. Tex sensor fusion (IMU), ju fler samplar du hanterar per sekund desto mindre drift och högre träffsäkerhet får du. Men absolut ett specialfall och i detta fall duger nog non blocking IO på main tråden.

edit: Concurrent kollektionerna i .NET är tänkta för fleranvändarsystem, de är inte designade för parallellisering på det sättet.

Visa signatur