Többszálas C # feladatokkal

Az számítógép programozás A "szál" kifejezés rövidítés a végrehajtási szálra, amelyben a processzor egy meghatározott utat követ a kódján. Az egynél több szál követésének koncepciója bevezette a többfeladatos és a többszálú téma témáját.

Egy alkalmazás egy vagy több folyamatot tartalmaz. Gondoljon egy folyamatra, mint a számítógépén futó programra. Most minden folyamatnak van egy vagy több szála. Lehet, hogy egy játékalkalmazás tartalmaz egy szálat az erőforrások betöltéséhez a lemezről, egy másik az AI elvégzéséhez, és egy másik, hogy a játékot kiszolgálóként futtassa.

A .NET / Windows rendszerben az operációs rendszer a processzor idejét egy szálra osztja. Minden szál nyomon követi a kivételes kezelőket és a prioritást, amelyen fut, és valahol meg kell mentenie a szál kontextusát, amíg fut. A szál kontextus az az információ, amelyet a szálnak folytatnia kell.

Többfeladat szálakkal

A szálak kevés memóriát igényelnek, és a létrehozásuk kevés időt vesz igénybe, így általában nem akar sokat használni. Ne feledje, hogy versenyeznek a processzoridőért. Ha a számítógép több CPU-val rendelkezik, akkor a Windows vagy a .NET futtathatja az egyes szálakat egy másik CPU-n, de ha több szál fut ugyanazon a processzoron, akkor egyszerre csak egy lehet aktív, és a szálak váltása eltart idő.

instagram viewer

A CPU fut egy szálat néhány millió utasításig, majd egy másik szálra vált. Az összes CPU-regisztert, az aktuális program végrehajtási pontját és a veremét el kell menteni valahol az első szálra, majd másutt vissza kell állítani a következő szálra.

Szálat létrehozása

A névtér rendszerben. Threading, megtalálja a szál típusát. A kivitelező szál (ThreadStart) létrehoz egy szálpéldányt. Ugyanakkor a közelmúltban C # kódot, akkor valószínűbb, hogy átad egy lambda kifejezést, amely bármilyen paraméterrel meghívja a metódust.

Ha nem biztos benne lambda kifejezések, érdemes lehet megnézni a LINQ-t.

Íme egy példa egy létrehozott és elindított szálra:

rendszer használata;
a System segítségével. threading;
névtér ex1
{
osztály program
{
nyilvános statikus érvénytelen Write1 ()
{
Konzol. Írj ('1');
Cérna. Alvás (500);
}
statikus érvénytelen Fő (karakterlánc [] args)
{
var feladat = új szál (Write1);
feladat. Rajt() ;
for (var i = 0; i <10; i ++)
{
Konzol. Írj ('0');
Konzol. Írj (feladat. Életben van? 'A': 'D');
Cérna. Alvás (150);
}
Konzol. ReadKey ();
}
}
}

Ez a példa csak az "1" beírása a konzolra. A fő szál tízszer egy "0" értéket ír a konzolra, minden alkalommal egy "A" vagy "D" betűvel, attól függően, hogy a másik szál még életben van vagy halott.

A másik szál csak egyszer fut és 1-et ír. A Write1 () szál fél másodperces késése után a szál befejeződik, és a Feladat. Az IsAlive a fő hurokban "D." értéket ad vissza

Menetkészlet és párhuzamos feladatkönyvtár

Ahelyett, hogy saját szálat készítené, hacsak nem igazán kell megtennie, használjon egy szálkészletet. A .NET 4.0 verzióból hozzáférhetünk a Feladat párhuzamos könyvtárához (TPL). Mint az előző példában, ismét szükségünk van egy kis LINQ-ra, és igen, ez mind lambda kifejezés.

A Feladatok a Menet medence a színfalak mögött, de a felhasznált számtól függően jobban ki kell használni a szálakat.

A TPL fő tárgya egy feladat. Ez egy osztály, amely aszinkron műveletet képvisel. A dolgok futásának a leggyakoribb módja a Feladat. Gyár. StartNew, mint itt:

Feladat. Gyár. StartNew (() => DoSomething ());

Ahol a DoSomething () a futtatott módszer. Lehetőség van egy feladat létrehozására, és nem lehet azonnal futtatni. Ebben az esetben csak a Feladatot használja így:

var t = új Feladat (() => Konzol. WriteLine nevû ( "Hello"));
...
t. Rajt();

Ez nem indítja el a szálat, amíg a .Start () meg nem hívódik. Az alábbi példában öt feladat található.

rendszer használata;
a System segítségével. threading;
a System segítségével. Threading. feladatok;
névtér ex1
{
osztály program
{
nyilvános statikus érvénytelen Write1 (int i)
{
Konzol. Írj (i);
Cérna. Alvás (50);
}
statikus érvénytelen Fő (karakterlánc [] args)
{
for (var i = 0; i <5; i ++)
{
var érték = i;
var runTask = Feladat. Gyár. StartNew (() => Write1 (érték));
}
Konzol. ReadKey ();
}
}
}

Futtassa ezt, és 0 és 4 közötti számjegyeket kap véletlenszerű sorrendben, például 03214. Ennek oka az, hogy a .NET határozza meg a feladat végrehajtásának sorrendjét.

Kíváncsi lehet, miért van szükség a var = = i értékre. Próbáld ki eltávolítani, és hívd az Write (i) elemet, és olyan váratlanul látni fogsz, mint az 55555. Miért ez? Ennek oka az, hogy a feladat az i értékét a feladat végrehajtásának időpontjában, nem pedig a feladat létrehozásakor mutatja. Hozzon létre egy új változó minden alkalommal a hurokban az öt érték mindegyikét helyesen tárolja és veszi fel.