Mitmekeermestamine ülesandes C #

arvuti programeerimine termin "niit" on lühike täitmisniidi jaoks, mille puhul protsessor järgib teie koodi täpsustatud teed. Korraga rohkem kui ühe niidi järgimise kontseptsioon tutvustab mitme ülesande ja keermestamise teemat.

Rakendusel on üks või mitu protsessi. Mõelge protsessile kui arvutis töötavale programmile. Nüüd on igal protsessil üks või mitu lõime. Mängurakendusel võib olla lõim ressursside laadimiseks kettalt, teisel AI ja teises, et mängu serverina käivitada.

NET / Windows korral eraldab opsüsteem protsessori aja niidile. Iga lõime jälgib erandkäitlejaid ja prioriteeti, milles see töötab, ning niidikonteksti peab kuskilt salvestama, kuni see töötab. Lõime kontekst on teave, mida lõime peab jätkama.

Mitmeülesanded lõimedega

Niidid võtavad natuke mälu ja nende loomine võtab natuke aega, nii et tavaliselt ei taha te paljusid kasutada. Pidage meeles, et nad konkureerivad protsessori aja pärast. Kui teie arvutis on mitu protsessorit, võib Windows või .NET käivitada iga lõime erinevas protsessoris, kuid kui samal protsessoril töötab mitu lõime, siis saab korraga aktiivne olla ainult üks ja niidide vahetamine võtab aega aeg.

instagram viewer

Protsessor töötab mõne miljoni juhise jaoks lõime ja lülitub seejärel teisele lõimele. Kõik protsessori registrid, praegune programmi täitmispunkt ja pinu tuleb esimese lõime jaoks kuskilt salvestada ja järgmise lõime jaoks kuskilt mujalt taastada.

Niidi loomine

Nimeruumi süsteemis. Keermestamine, leiate lõime tüübi. Ehitaja niit (ThreadStart) loob lõime eksemplari. Kuid viimasel ajal C # koodi, läbib see tõenäolisemalt lambda-avaldise, mis kutsub meetodit mis tahes parameetritega.

Kui te pole kindel lambda väljendid, võib-olla tasub vaadata LINQ-i.

Siin on näide loodud ja käivitatud lõimest:

süsteemi kasutamine;
kasutades süsteemi. Keermestamine;
nimeruum ex1
{
klassi programm
{
avalik staatiline tühine Write1 ()
{
Konsool. Kirjuta ('1');
Niit. Uni (500);
}
static void Main (string [] args)
{
var ülesanne = uus teema (Write1);
ülesanne. Algus ();
jaoks (var i = 0; i <10; i ++)
{
Konsool. Kirjuta ('0');
Konsool. Kirjutage (ülesanne. On elus? 'A': 'D');
Niit. Uni (150);
}
Konsool. ReadKey ();
}
}
}

Kõik see näide kirjutab konsoolile "1". Põhilõng kirjutab konsoolile kümme korda numbri "0", millele järgneb iga kord "A" või "D" sõltuvalt sellest, kas teine ​​teema on endiselt elus või surnud.

Teine niit töötab ainult üks kord ja kirjutab numbri "1." Pärast poole sekundi pikkust viivitust lõimes Write1 () lõpeb lõime ja ülesanne. IsAlive põhisilmus tagastab nüüd tähe D.

Keermebassein ja tööülesannete paralleelkogu

Enda lõime loomise asemel - kui teil seda tegelikult vaja pole - kasutage lõimebasseini. Alates .NET 4.0 on meil juurdepääs Task Parallel Library (TPL). Nagu eelmises näites, vajame jällegi natuke LINQ-i ja jah, see kõik on lambda-väljendid.

Ülesanded kasutavad Keermebassein kulisside taga, kuid kasutage niite paremini, sõltuvalt kasutatavast arvust.

TPL-i peamine objekt on Ülesanne. See on klass, mis tähistab asünkroonset toimingut. Kõige tavalisem viis asjade käivitamiseks on Ülesanne. Tehas. AlustaUus nagu:

Ülesanne. Tehas. StartNew (() => DoSomething ());

Kus DoSomething () on juhitav meetod. Ülesande on võimalik luua ja seda mitte kohe käivitada. Sel juhul kasutage ülesannet lihtsalt järgmiselt:

var t = new Task (() => Console. WriteLine ("Tere"));
...
t. Algus ();

See ei käivita lõime enne, kui .Start () kutsutakse. Allpool toodud näites on viis ülesannet.

süsteemi kasutamine;
kasutades süsteemi. Keermestamine;
kasutades süsteemi. Keermestamine. Ülesanded;
nimeruum ex1
{
klassi programm
{
avalik staatiline tühine Write1 (int i)
{
Konsool. Kirjutage (i);
Niit. Uni (50);
}
static void Main (string [] args)
{
jaoks (var i = 0; i <5; i ++)
{
var väärtus = i;
var runningTask = Ülesanne. Tehas. StartNew (() => Write1 (väärtus));
}
Konsool. ReadKey ();
}
}
}

Käivitage see ja saate numbrid 0 kuni 4 väljundina juhuslikus järjekorras, näiteks 03214. Selle põhjuseks on asjaolu, et ülesande täitmise järjekorra määrab .NET.

Teil võib tekkida küsimus, miks on vajalik var väärtus = i. Proovige see eemaldada ja helistage Write (i) -le ning näete midagi ootamatut, näiteks 55555. Miks on see? Selle põhjuseks on asjaolu, et ülesanne näitab i väärtust ülesande täitmise ajal, mitte siis, kui ülesanne loodi. Luues uue muutuja iga kord ahelas on kõik viis väärtust õigesti salvestatud ja valitud.