2013-05-17 4 views
2
 var tokenSource2 = new CancellationTokenSource(); 
     CancellationToken ct = tokenSource2.Token; 

     var task = Task.Factory.StartNew(() => { 
        Thread.Sleep(4000); 
        Console.WriteLine("Done"); 
        ct.ThrowIfCancellationRequested(); 
        }, ct); 

     Thread.Sleep(1000); Look here! <--- 
     tokenSource2.Cancel(); 

     try 
     { 
      Console.WriteLine("Wait"); 
      task.Wait(); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("Task was canceled"); 
     } 

Не могу понять, почему, если я прокомментирую эту строку, все работает нормально, и исключение попадает в основной поток, но если я оставил эту строку, исключение выбрано в дочернем потоке строка с ct.ThrowIfCancellationRequested(); В обоих случаях есть один экземпляр токена отмены. Я новичок в multithreadin, поэтому я определенно пропущу что-то.Многопоточность - не понимаю ситуацию

Я попытался следующий код

static void Main(string[] args) 
    { 
     Thread.CurrentThread.Name = "Main"; 

     Console.WriteLine("Name of the current thread is " + Thread.CurrentThread.Name); 

     var tokenSource2 = new CancellationTokenSource(); 
     CancellationToken ct = tokenSource2.Token; 
     var task = Task.Factory.StartNew(() => 
     { 
      Thread.Sleep(4000); 
      Console.WriteLine("Done"); 

      try 
      { 
       ct.ThrowIfCancellationRequested(); // If I remove the try/catch here will be unhandled exception 
      } 
      catch (OperationCanceledException exp) 
      { 
       Console.WriteLine("Task was started then canceled"); 
      } 

     }, ct);//ontinueWith(OnProcessImageEnded); 

     Thread.Sleep(1000); 
     tokenSource2.Cancel(); 

     try 
     { 
      Console.WriteLine("Wait"); 
      task.Wait(); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine("Task was canceled"); 
     } 

     Console.WriteLine("Task was finished"); 

     Console.WriteLine(task.Status); 

I исключение процесса в потоке данных задачи в настоящее время, но это приводит к положению задачи не должен быть установлен Отмененные. Я думаю, это потому, что теперь задача не может поймать исключение для ее обработки. Каков правильный путь?

Я нашел http://msdn.microsoft.com/en-us/library/ee191553.aspx этот пример, и у него такая же проблема! если мы нажмем на «c» во время выполнения, он выкинет необработанное исключение, когда мы попытаемся реконструировать, вызвав externalToken.ThrowIfCancellationRequested(); ... Я в замешательстве. Я использую x64 Win 7, 4.5 .net framework

ответ

2

Когда вы прокомментируете строку, возможно, наша задача отменена еще до ее запуска. Следовательно, вы получаете исключение. Когда вы добавляете спящий режим - в основном, он будет запущен, поэтому отмена будет выполняться в рамках задачи с вашего звонка до ThrowIfCancellationRequested

+0

ОК, но я думал, что поведение должно быть одинаковым. Почему у него есть смысл запускать задание или нет? Здесь docs info: Когда экземпляр задачи замечает исключение OperationCanceledException, созданное кодом пользователя, он сравнивает токен исключения с ассоциированным токеном (смотрите следующий комментарий, он слишком длинный для одного) –

+0

(тот, который был передан API, который создал Задача). Если они одинаковы, а свойство IsCancellationRequested token возвращает true, задача интерпретирует это как подтверждение отмены и перехода в состояние «Отменено». Если вы не используете метод Wait или WaitAll для ожидания задачи, задача просто устанавливает свой статус в Canceled .--- Как я понимаю, это означает, что исключение не должно быть выбрано вообще, если не существует метода ожидания и должен быть брошен в основной поток в попытке с помощью метода Wait. Я взял его с http://msdn.microsoft.com/en-us/library/dd997396(v=vs.100).aspx –

+0

Я думаю, что я не понял эту концепцию.Итак, я рассмотрел еще несколько примеров и понял, что если поток задачи не запущен, мы должны поймать исключение в вызывающем потоке, но если он уже запущен, нам нужно исключить исключение отмены в потоке задачи, не вызвав его. Я прав? –

0

Отложите на documentation для этого.

Task.Wait Метод

AggregateException

Задача была отменена -или- было брошено исключение во время выполнения задачи. Если задача была отменена, значение AggregateException содержит событие OperationCanceledException в его коллекции InnerExceptions.

По существу, это состояние гонки, если вы делаете это до task.Wait во время победы.

+0

Извините, но я не понял вашего ответа. Что вы имеете в виду? Когда отменяется вызов, задача все еще работает (возможно, поток спящий, но это неважно, я думаю). Я говорю о Sleep с задержкой 1 секунда в основной теме. Как это может повлиять на то, где исключено исключение? Мы можем удалить task.Wait(), и исключение все еще попадает в поток задачи, но, насколько я понимаю. он не должен улавливать его, потому что, если мы не вызываем метод Wait, внутренний обработчик задачи захватывает его и устанавливает статус Canseled. Пожалуйста, дайте мне понять :) –

Смежные вопросы