Monisäikeinen C # -tehtävissä

tietokoneohjelmointi termi "säie" on lyhenne suoritusjonoon, jossa prosessori seuraa määritettyä polkua koodisi läpi. Käsite seurata useampaa kuin yhtä säiettä kerrallaan esittelee monitehtävän ja monisäikeistämisen aiheen.

Sovelluksessa on yksi tai useampi prosessi. Ajattele prosessia tietokoneellasi käynnissä olevana ohjelmana. Nyt jokaisessa prosessissa on yksi tai useampi säie. Pelisovelluksessa voi olla säie resurssien lataamiseksi levyltä, toisessa AI ja toisessa pelin suorittamiseksi palvelimena.

.NET / Windows-käyttöjärjestelmässä allokoi prosessorin aika säikeelle. Jokainen ketju seuraa poikkeuskäsittelijöitä ja prioriteettia, jolla se toimii, ja sen on jonnekin tallennettava säiekonteksti, kunnes se suoritetaan. Langan konteksti on tietoa, jota langan on jatkettava.

Monitehtävä langoilla

Langat vievät vähän muistia ja niiden luominen vie vähän aikaa, joten yleensä et halua käyttää monia. Muista, että he kilpailevat prosessorin ajasta. Jos tietokoneellasi on useita suorittimia, Windows tai .NET saattaa käyttää kutakin säiettä eri CPU: lla, mutta jos useita ketjuja kulkee samalla CPU: lla, niin vain yksi voi olla aktiivinen kerrallaan ja ketjujen vaihtaminen vie aika.

instagram viewer

Suoritin suorittaa säiettä muutaman miljoonan käskyn ajan, ja sitten se vaihtaa toiseen säieeseen. Kaikki CPU-rekisterit, nykyinen ohjelman suorituspiste ja pino on tallennettava jonnekin ensimmäistä säiettä varten ja palautettava sitten muualta seuraavalle säieelle.

Langan luominen

Nimitilajärjestelmässä. ketjuttaminen, löydät langan tyypin. Rakentajalanka (ThreadStart) luo ketjun esiintymän. Viime aikoina kuitenkin C # koodilla, se läpäisee todennäköisemmin lambda-lausekkeen, joka kutsuu menetelmää millä tahansa parametreilla.

Jos olet epävarma lambda-ilmaisut, saattaa olla syytä tarkistaa LINQ.

Tässä on esimerkki luodusta ja aloitetusta säikeestä:

käyttämällä järjestelmää;
järjestelmän avulla. Threading;
nimitila ex1
{
luokkaohjelma
{
julkinen staattinen tyhjä Write1 ()
{
Konsoli. Kirjoita ('1');
Lanka. Sleep (500);
}
staattinen void Main (merkkijono [] args)
{
var tehtävä = uusi säie (Write1);
tehtävä. Alkaa() ;
for (var i = 0; i <10; i ++)
{
Konsoli. Kirjoita ('0');
Konsoli. Kirjoita (tehtävä. On elossa? 'A': 'D');
Lanka. Sleep (150);
}
Konsoli. ReadKey ();
}
}
}

Kaikki tämä esimerkki kirjoittaa "1" konsoliin. Päälanka kirjoittaa konsolin "0" 10 kertaa, jota seuraa joka kerta "A" tai "D" riippuen siitä, onko toinen säie edelleen elossa vai kuollut.

Toinen säie toimii vain kerran ja kirjoittaa "1." Puoli sekunnin viiveen jälkeen Write1 () -ketjussa viestiketju päättyy ja tehtävä. IsAlive pääsilmukassa palauttaa nyt "D."

Kiertoallas ja tehtävien rinnakkaiskirjasto

Oman langan luomisen sijasta, jollei sinun todella tarvitse tehdä sitä, käytä lanka-allasta. .NET 4.0: sta, meillä on pääsy Task Parallel Library (TPL) -tehtävään. Kuten edellisessä esimerkissä, tarvitsemme jälleen vähän LINQ: ta, ja kyllä, se kaikki on lambda-lausekkeita.

Tehtävät käyttää Kiertoallas kulissien takana, mutta hyödyntävät lankoja paremmin käytetyn määrän mukaan.

TPL: n pääobjekti on tehtävä. Tämä on luokka, joka edustaa asynkronista toimintaa. Yleisin tapa aloittaa asiat juoksemalla on Tehtävä. Tehdas. AloitaUusi kuten:

Tehtävä. Tehdas. StartNew (() => DoSomething ());

Missä DoSomething () on ajettu menetelmä. On mahdollista luoda tehtävä eikä sitä voida suorittaa heti. Käytä tällöin vain Tehtävää näin:

var t = uusi tehtävä (() => konsoli. WriteLine ( "Hello"));
...
T. Alkaa();

Tämä ei aloita ketjua, ennen kuin .Start () -soittoa kutsutaan. Seuraavassa esimerkissä on viisi tehtävää.

käyttämällä järjestelmää;
järjestelmän avulla. Threading;
järjestelmän avulla. Threading. tehtävät;
nimitila ex1
{
luokkaohjelma
{
julkinen staattinen void Write1 (int i)
{
Konsoli. Kirjoita (i);
Lanka. Sleep (50);
}
staattinen void Main (merkkijono [] args)
{
for (var i = 0; i <5; i ++)
{
var arvo = i;
var runningTask = Tehtävä. Tehdas. StartNew (() => Write1 (arvo));
}
Konsoli. ReadKey ();
}
}
}

Suorita se ja saat numerot 0 - 4 lähtöön satunnaisessa järjestyksessä, kuten 03214. Tämä johtuu siitä, että .NET määrittää tehtävän suorittamisjärjestyksen.

Saatat ihmetellä, miksi var arvo = i tarvitaan. Yritä poistaa se ja soittaa Write (i) -sovellukselle, niin näet jotain odottamatonta, kuten 55555. Miksi tämä on? Se johtuu siitä, että tehtävä näyttää i: n arvon tehtävän suorittamisen ajankohtana, ei tehtävän luontihetkellä. Luomalla uuden muuttuja Joka kerta silmukassa jokainen viidestä arvosta on tallennettu oikein ja poimittu.