Flertråd i C # With Tasks

De dataprogramering begrepet "tråd" er en forkortelse for utførelsestråd, der en prosessor følger en spesifisert bane gjennom koden din. Konseptet med å følge mer enn en tråd om gangen introduserer emnet multi-tasking og multi-threading.

En applikasjon har en eller flere prosesser i seg. Tenk på en prosess som et program som kjører på datamaskinen din. Nå har hver prosess en eller flere tråder. Et spillprogram kan ha en tråd for å laste inn ressurser fra disk, en annen for å gjøre AI og en annen for å kjøre spillet som en server.

I .NET / Windows tildeler operativsystemet prosessortid til en tråd. Hver tråd holder oversikt over unntaksbehandlere og prioriteringen den kjører, og den har et sted å lagre trådkonteksten til den kjører. Trådkontekst er informasjonen som tråden trenger å gjenoppta.

Fleroppgave med tråder

Tråder tar litt minne, og det tar litt tid å lage dem, så vanligvis vil du ikke bruke mange. Husk at de konkurrerer om prosessortid. Hvis datamaskinen din har flere CPUer, kan Windows eller .NET kanskje kjøre hver tråd på en annen CPU, men hvis flere tråder kjører på samme CPU, da er det bare en som kan være aktiv om gangen og å bytte tråder tar tid.

instagram viewer

CPU kjører en tråd for noen millioner instruksjoner, og deretter bytter den til en annen tråd. Alle CPU-registre, gjeldende programutføringspunkt og stabel må lagres et sted for den første tråden og deretter gjenopprettes fra et annet sted for neste tråd.

Opprette en tråd

I navnerommet System. Threading, finner du trådtypen. Konstruktortråden (ThreadStart) oppretter en forekomst av en tråd. Imidlertid i det siste C # kode, er det mer sannsynlig at det passerer i et lambda-uttrykk som kaller metoden med noen parametere.

Hvis du er usikker lambda-uttrykk, kan det være verdt å sjekke ut LINQ.

Her er et eksempel på en tråd som er opprettet og startet:

bruker System;
bruker System. threading;
navneområde ex1
{
klasse Program
{
offentlig statisk tomrom Skriv1 ()
{
Console. Skriv ('1');
Tråd. Søvn (500);
}
statisk tomrom Main (streng [] args)
{
var oppgave = ny tråd (Skriv1);
oppgave. Start() ;
for (var i = 0; i <10; i ++)
{
Console. Skriv ('0');
Console. Skriv (oppgave. Er i live? 'A': 'D');
Tråd. Søvn (150);
}
Console. ReadKey ();
}
}
}

Alt dette eksemplet gjør er å skrive "1" til konsollen. Hovedtråden skriver en "0" til konsollen 10 ganger, hver gang etterfulgt av en "A" eller "D" avhengig av om den andre tråden fremdeles er levende eller død.

Den andre tråden kjører bare en gang og skriver en "1." Etter halvt sekunders forsinkelse i Writ1 () -tråden, er tråden ferdig og oppgaven. IsAlive i hovedløkken returnerer nå "D."

Trådbasseng og oppgave Parallellbibliotek

I stedet for å lage din egen tråd, med mindre du virkelig trenger å gjøre det, bruk et trådbasseng. Fra .NET 4.0 har vi tilgang til Task Parallel Library (TPL). Som i forrige eksempel trenger vi igjen litt LINQ, og ja, det er alt lambda-uttrykk.

Oppgaver bruker Gjengbasseng bak kulissene, men utnytter trådene bedre avhengig av antall i bruk.

Hovedobjektet i TPL er en oppgave. Dette er en klasse som representerer en asynkron operasjon. Den vanligste måten å starte ting på å løpe på er med oppgaven. Fabrikk. StartNy som i:

Oppgave. Fabrikk. StartNew (() => DoSomething ());

Hvor DoSomething () er metoden som kjøres. Det er mulig å lage en oppgave og ikke få den kjørt umiddelbart. I så fall er det bare å bruke oppgaven slik:

var t = new Oppgave (() => Konsoll. Writeline ( "Hello"));
...
t. Start();

Det starter ikke tråden før .Start () heter. I eksemplet nedenfor er fem oppgaver.

bruker System;
bruker System. threading;
bruker System. Threading. oppgaver;
navneområde ex1
{
klasse Program
{
offentlig statisk tomrom Skriv1 (int i)
{
Console. Skriv (i);
Tråd. Søvn (50);
}
statisk tomrom Main (streng [] args)
{
for (var i = 0; i <5; i ++)
{
var verdi = i;
var runningTask = Oppgave. Fabrikk. StartNew (() => Skriv1 (verdi));
}
Console. ReadKey ();
}
}
}

Kjør det, så får du sifrene 0 til 4 i en tilfeldig rekkefølge, for eksempel 03214. Det er fordi rekkefølgen på utførelse av oppgave bestemmes av .NET.

Du lurer kanskje på hvorfor var-verdien = i er nødvendig. Prøv å fjerne det og ringe Skriv (i), så ser du noe uventet som 55555. Hvorfor er det sånn? Det er fordi oppgaven viser verdien av i på det tidspunktet oppgaven utføres, ikke når oppgaven ble opprettet. Ved å lage en ny variabel hver gang i løkken, blir hver av de fem verdiene lagret og hentet riktig.