Страница 432 из 502
<b> // Проверить, отменена ли задача,</b>
<b> // прежде чем запускать ее.</b>
<b> cancelTok.ThrowIfCancellationRequested();</b>
<b> Console.WriteLine("MyTask() запущен");</b>
<b> for(int count = 0; count < 10; count++) {</b>
<b> // В данном примере для отслеживания отмены задачи применяется опрос,</b>
<b> if(cancelTok.IsCancellationRequested) {</b>
<b> Console.WriteLine("Получен запрос на отмену задачи.");</b>
<b> cancelTok.ThrowIfCancellationRequested();</b>
<b> }</b>
<b> Thread.Sleep(500);</b>
<b> Console.WriteLine("В методе MyTask() подсчет равен " + count );</b>
<b> }</b>
<b> Console.WriteLine("MyTask завершен");</b>
<b> }</b>
<b> static void Main() {</b>
<b> Console.WriteLine("Основной поток запущен.");</b>
<b> // Создать объект источника признаков отмены.</b>
<b> CancellationTokenSource cancelTokSrc = new CancellationTokenSource();</b>
<b> // Запустить задачу, передав признак отмены ей самой и делегату.</b>
<b> Task tsk = Task.Factory.StartNew(MyTask, cancelTokSrc.Token,</b>
<b> cancelTokSrc.Token);</b>
<b> // Дать задаче возможность исполняться вплоть до ее отмены.</b>
<b> Thread.Sleep(2000);</b>
<b> try {</b>
<b> // Отменить задачу.</b>
<b> cancelTokSrc.Cancel();</b>
<b> // Приостановить выполнение метода Main() до тех пор,</b>
<b> // пока не завершится задача tsk.</b>
<b> tsk.Wait();</b>
<b> } catch (AggregateException exc) {</b>
<b> if(tsk.IsCanceled)</b>
<b> Console.WriteLine("nЗадача tsk отменена");</b>
<b> // Для просмотра исключения снять комментарии со следующей строки кода:</b>
<b> // Console.WriteLine(exc);</b>
<b> } finally {</b>
<b> tsk.Dispose();</b>
<b> cancelTokSrc.Dispose();</b>
<b> }</b>
<b> Console.WriteLine("Основной поток завершен.");</b>
<b> }</b>
<b>}</b>
Ниже приведен результат выполнения этой программы. Обратите внимание на то что задача отменяется через 2 секунды.
<b>Основной поток запущен.</b>
<b>MyTask() запущен</b>
<b>В методе MyTask() подсчет равен 0</b>
<b>В методе MyTask() подсчет равен 1</b>
<b>В методе MyTask() подсчет равен 2</b>
<b>В методе MyTask() подсчет равен 3</b>
<b>Получен запрос на отмену задачи.</b>
<b>Задача tsk отменена</b>
<b>Основной поток завершен.</b>
Как следует из приведенного выше результата, выполнение метода MyTask() отменяется в методе Main() лишь две секунды спустя. Следовательно, в методе MyTask() выполняются четыре шага цикла. Когда же перехватывается исключение AggregateException, проверяется состояние задачи. Если задача tsk отменена, что и должно произойти в данном примере, то об этом выводится соответствующее сообщение. Следует, однако, иметь в виду, что когда сообщение AggregateException генерируется в ответ на отмену задачи, то это еще не свидетельствует об ошибке, а просто означает, что задача была отменена.
Выше были изложены лишь самые основные принципы, положенные в основу отмены задачи и генерирования исключения AggregateException. Тем не менее эта тема намного обширнее и требует от вас самостоятельного и углубленного изучения, если вы действительно хотите создавать высокопроизводительные, масштабируемые приложения.
Другие средства организации задач
В предыдущих разделах был описан ряд понятий и основных способов организации и исполнения задач. Но имеются и другие полезные средства. В частности, задачи можно делать вложенными, когда одни задачи способны создавать другие, или же порожденными, когда вложенные задачи оказываются тесно связанными с создающей их задачей.
В предыдущем разделе было дано краткое описание исключения AggregateException, но у него имеются также другие особенности, которые могут оказаться весьма полезными. К их числу относится метод Flatten(), применяемый для преобразования любых внутренних исключений типа AggregateException в единственное исключение AggregateException. Другой метод, Handle(), служит для обработки исключения, составляющего совокупное исключение AggregateException.