NET, Отмени задачата

Версия 4.0 на .NET Framework въведе нова подсистема, която предоставя структуриран, макар и много удобен начин за отмяна на задача. Тази нова подсистема се основава на концепцията за флаг за анулиране. Токените за анулиране се поддържат в класа Task, наред с други неща, чрез фабричния метод StartNew().

Анулирането на задача обикновено става по следния начин. Първо се получава флаг за анулиране от източника на флаг за анулиране. След това този флаг се предава на задачата, след което тя трябва да я наблюдава за заявка за анулиране. (Тази заявка може да идва само от източник на флаг за отмяна.) Ако бъде получена заявка за отмяна, задачата трябва да бъде изпълнена.

В някои случаи това е достатъчно просто да прекрати задачата без допълнителни действия, а в други методътThrowIfCancellationRequested() трябва да бъде извикан от задачата за флага за отмяна. Това уведомява кода за отмяна, че задачата е била отменена. Сега нека разгледаме по-подробно процеса на отмяна на задача.

Токенът за анулиране е екземпляр на обект от тип CancellationToken, т.е. структура, дефинирана в пространството на имената System.Threading. Има няколко свойства и метода, дефинирани в структурата на CancellationToken, но ние ще използваме две от тях. Първият е свойствотоIsCancellationRequested само за четене. Връща boolean true, ако е поискано отмяна на задача за извикващата характеристика, в противен случай boolean false. И второто е методът ThrowIfCancellationRequested().

Ако флагът за анулиране, за който се извиква този метод, е получил заявка за анулиране, тогава в този метод се хвърля изключение OperationCanceledException. Иначе никакви действияизпълнени. В кода за анулиране можете да организирате улавянето на споменатото изключение, за да сте сигурни, че анулирането на задачата действително е настъпило. Обикновено AggregateException първо се улавя за тази цел и след това вътрешното му изключение се анализира с помощта на свойството InnerException или InnerExceptions. (Свойството InnerExceptions е колекция от изключения.)

Токенът за анулиране се получава от източника на токена за анулиране, който е обект от класа CancellationTokenSource, дефиниран в пространството от имена System.Threading. За да получите тази функция, първо трябва да създадете екземпляр на обект от тип CancellationTokenSource. (Можете да използвате конструктора по подразбиране на класа CancellationTokenSource за тази цел.) Токенът за анулиране, свързан с този източник, е достъпен чрез свойствотоToken само за четене. Това е атрибутът, който трябва да бъде предаден на отменената задача.

За анулиране на задача трябва да се получи копие на флага за анулиране и трябва да се организира контрол на този флаг, за да се проследи самото анулиране. Това проследяване може да се извърши по три начина: чрез запитване, чрез метод за обратно извикване и чрез използване на дръжка за изчакване. Най-лесният начин е да организирате проучване и затова този метод ще бъде разгледан тук. За целите на запитването задачата проверява свойството IsCancellationRequested, споменато по-горе на флага за отмяна. Ако това свойство съдържа булевата стойност true, тогава е поискано анулиране и задачата трябва да бъде изпълнена.

Едно проучване може да бъде много ефективно, ако се направи правилно. Така че, ако задачата съдържа вложени цикли, тогава проверката на свойството IsCancellationRequested във външния цикъл често дава по-добър резултат от неговотопроверка на всяка стъпка от вътрешния цикъл.

Създаването на задача, от която методът ThrowIfCancellationRequested() се извиква, когато бъде отменена, обикновено изисква предаване на флаг за отмяна както на самата задача, така и на конструктора на класа Task, директно или индиректно чрез метода StartNew(). Предаването на флага за отмяна на самата задача ви позволява да промените състоянието на отменената задача в заявката за отмяна от външен код.

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

Фактът, че дадена задача е отменена, може да се провери по различни начини. Подходът тук е да се провери стойността на свойството IsCanceled на екземпляр на обект от тип Task. Ако тази булева стойност е вярна, тогава задачата е отменена.

Следващата програма демонстрира как да отмените задача. Той използва запитване, за да наблюдава състоянието на флага за отмяна. Имайте предвид, че методът ThrowIfCancellationRequested() се извиква след въвеждане на метода MyTask(). Това прави възможно изпълнението на задачата, ако е била отменена преди да започне. Вътре в цикъла се проверява свойството IsCancellationRequested. Ако това свойство съдържа булевата стойност true и е зададено след извикването на метода Cancel() на екземпляра на източника на флага за отмяна, тогава се показва съобщение за отмяна и методът ThrowIfCancellationRequested() се извиква за отмяна на задачата:

Както можете да видите от примера по-горе, методът MyTask() се отменя в метода Main() само две секунди по-късно. Следователно има четири стъпки на цикъл в метода MyTask(). Когато AggregateException бъде уловен,проверява се състоянието на задачата. Ако задачата tsk бъде отменена, което трябва да се случи в този пример, тогава се показва подходящо съобщение за това. Обърнете внимание обаче, че когато съобщение AggregateException е хвърлено в отговор на отменена задача, това все още не е грешка, а просто означава, че задачата е отменена.

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