Мулти-резба в C # със задачи

Най- компютърно програмиране Терминът "нишка" е кратък за нишка на изпълнение, в който процесор следва определен път през вашия код. Концепцията за следване на повече от една нишка наведнъж въвежда темата за многозадачност и многорежеща резба.

Приложението има един или повече процеси в него. Мислете за процес като програма, работеща на вашия компютър. Сега всеки процес има една или повече нишки. Приложението за игри може да има нишка за зареждане на ресурси от диска, друг да прави AI и друг, който да стартира играта като сървър.

В .NET / Windows операционната система разпределя времето на процесора за нишка. Всяка нишка следи обработчиците на изключения и приоритета, при който се изпълнява, и има къде да запише контекста на нишката, докато не се изпълнява. Контекстът на нишката е информацията, която нишката трябва да възобнови.

Мултизадачи с нишки

Нишките заемат малко памет и създаването им отнема малко време, така че обикновено не искате да използвате много. Не забравяйте, че те се състезават за време на процесора. Ако вашият компютър има няколко процесора, тогава Windows или .NET може да стартира всяка нишка в различен процесор, но ако няколко нишки работят в един и същ процесор, тогава само един може да бъде активен в даден момент и превключването на нишки отнема време.

instagram viewer

Процесорът пуска нишка за няколко милиона инструкции и след това преминава към друга нишка. Всички регистри на процесора, текущата точка на изпълнение на програмата и стека трябва да бъдат записани някъде за първата нишка и след това възстановени от някъде другаде за следващата нишка.

Създаване на нишка

В пространството на имена Система. Threading, ще намерите типа нишка. Конструкторната нишка (ThreadStart) създава инстанция на нишка. Въпреки това, наскоро ° С# код, по-вероятно е да премине в ламбда израз, който извиква метода с каквито и да е параметри.

Ако не сте сигурни за ламбда изрази, може да си струва да проверите LINQ.

Ето пример за нишка, която се създава и стартира:

използване на System;
използвайки System. Threading;
пространство от имена ex1
{
клас програма
{
публична статична невалид Write1 ()
{
Console. Напишете ('1');
Нишка. Сън (500);
}
static void Main (string [] аргументи)
{
var задача = нова тема (Write1);
задача. Старт ();
за (var i = 0; i <10; и ++)
{
Console. Напишете ('0');
Console. Пишете (задача). IsAlive? 'A': 'D');
Нишка. Сън (150);
}
Console. ReadKey ();
}
}
}

Всичко, което този пример прави, е да напишете "1" на конзолата. Основната нишка пише "0" на конзолата 10 пъти, всеки път последвана от "A" или "D" в зависимост от това дали другата нишка все още е жива или мъртва.

Другата нишка работи само веднъж и пише "1." След закъснението за половин секунда в нишката Write1 (), нишката завършва и задачата. IsAlive в основния цикъл сега връща "D."

Библиотека с нишки и паралелна задача

Вместо да създадете своя собствена нишка, освен ако наистина не е необходимо да го направите, използвайте басейн от конци. От .NET 4.0 имаме достъп до библиотеката с паралелни задачи (TPL). Както в предишния пример, отново се нуждаем от малко LINQ и да, всичко това са ламбда изрази.

Задачите използва Резбован басейн зад кулисите, но по-добре използвайте нишките в зависимост от броя на използваните.

Основният обект в TPL е задача. Това е клас, който представлява асинхронна операция. Най-разпространеният начин да започнете нещата е със задачата. Фабрика. StartNew като в:

Задача. Фабрика. StartNew (() => DoSomething ());

Къде DoSomething () е методът, който се изпълнява. Възможно е да създадете задача и да не я стартирате веднага. В този случай просто използвайте задача като този:

var t = нова задача (() => конзола. WriteLine ( "Hello"));
...
T. Започнете ();

Това не стартира нишката, докато не се извика .Start (). В примера по-долу са пет задачи.

използване на System;
използвайки System. Threading;
използвайки System. Threading. задачи;
пространство от имена ex1
{
клас програма
{
публична статична празнота Write1 (int i)
{
Console. Напишете (i);
Нишка. Сън (50);
}
static void Main (string [] аргументи)
{
за (var i = 0; i <5; и ++)
{
стойност стойност = i;
var runningTask = Задача. Фабрика. StartNew (() => Write1 (стойност));
}
Console. ReadKey ();
}
}
}

Стартирайте това и ще получите изход от цифри от 0 до 4 в някакъв произволен ред, като 03214. Това е така, защото редът на изпълнение на задачите се определя от .NET.

Може би се чудите защо е необходима стойността на var = = i. Опитайте да го премахнете и да се обадите на Write (i) и ще видите нещо неочаквано като 55555. Защо е това? Това е така, защото задачата показва стойността на i по времето, когато се изпълнява задачата, а не когато е създадена. Чрез създаване на нов променлив всеки път в цикъла всяка от петте стойности се съхранява правилно и се избира.

instagram story viewer