2013-09-11 6 views
5

Когда я отменяю задачу, результат ожидания по-прежнему возвращает true для свойства IsCanceled. Кажется, что-то идет не так.Задача IsCanceled является ложной, а я отменил

Просьба сообщить. Это код:

CancellationTokenSource _cancelLationToken = new CancellationTokenSource(); 

private async void Button_Click(object sender, EventArgs e) 
{ 
    _cancelLationToken = new CancellationTokenSource(); 
    _cancelLationToken.Token.Register(theCallBack); 
    var myTaskToWaitFor = Task.Factory.StartNew(() => WorkHard(_cancelLationToken.Token), _cancelLationToken.Token); 
    await myTaskToWaitFor; 

    int i=0; 

    if(myTaskToWaitFor.IsCanceled) 
     i = i; //breakpoint for debugging 
    else 
     i = i; //breakpoint for debugging <== always ends here... :-(
} 

private void WorkHard(CancellationToken token) 
{ 
    for(int i = 0; i < 100000000; i++) 
     if(token.IsCancellationRequested) 
      break; 
     else 
      Math.Acos(Math.Pow(i, i/10000000)); 
} 

public void theCallBack() 
{ 
    //todo: do something 
} 

private void CancelButton_Click(object sender, EventArgs e) 
{ 
    _cancelLationToken.Cancel(); 
} 

Когда я попал в CancelButton и, следовательно, вызвать метод CancelButton_Click, метод CallBack срабатывает. Но ... когда я проверяю myTaskToWaitFor.IsCanceled, всегда возвращается false, и я получаю эту информацию: Id = 1, Status = RanToCompletion, Method = "{null}". Почему статус не отменен или что-то еще?

Когда я использую http://msdn.microsoft.com/en-us/library/system.threading.cancellationtoken.throwifcancellationrequested.aspx

так:

private void WorkHard(CancellationToken token) 
{ 
    for(int i = 0; i < 100000000; i++) 
     if(token.IsCancellationRequested) 
      token.ThrowIfCancellationRequested(); 
     else 
      Math.Acos(Math.Pow(i, i/10000000)); 
} 

я только получить некоторые ошибки в режиме отладки и кажется myTaskToWaitFor фактически отменен, но код не продолжается (по-прежнему программа отключается из-за исключения). Любые мысли? С наилучшими пожеланиями,

Matthijs

Edit:.

тест с TrowIfCancellationRequested был основан на "При вызове ThrowIfCancellationRequested на CancellationToken, который отменен, он будет бросать OperationCanceledException Параллельная библиотека задач знает , что этот тип исключения представляет собой отмену, а не отказ, и будет обрабатывать по-разному. Например, задача имеет свойство называемый IsCanceled, автоматически становится истинным, когда при вызове метода OperationCanceledException выполняется метод async . "Из книги асинхронным в C# 5.0 Алекс Дэвис.

Вот почему я думал, что я мог ожидать myTaskToWaitFor.IsCancelled вернуть истинный и код будет продолжаться.

+0

Версия с 'ThrowIfCancellationRequested' верна - что-то происходит там неожиданно? Ожидается, что это сообщит об исключении, однако - вам нужно обработать это –

+0

Как я могу обработать исключение перед проверкой myTaskToWaitForGetCashReport.IsCanceled? Если я добавлю попытку уловить «\t var myTaskToWaitFor = Task.Factory.StartNew (() => WorkHard (_cancelLationToken.Token), _cancelLationToken.Token); \t wait myTaskToWaitFor;" поле myTaskToWaitFor неизвестно (конечно ...). Когда я также добавляю чек myTaskToWaitFor.IsCanceled в попытке ... Я перехожу только на часть catch. Должен ли я сделать поле bool перед попыткой и установить его либо внутри try, либо в catch? Это единственное решение? (myTaskToWaitFor.IsCanceled (конечно) неизвестно в catch) – user369122

+1

вы 'try' /' catch' вокруг 'await'. К тому времени переменная известна. –

ответ

7

ThrowIfCancellationRequested() идеальный способ сигнализации, что вы существуют в связи с отменой аннулирования. Этот будет представить себя как исключение у вызывающего, но вы можете справиться с этим, имея try/catch вокруг await и просто проверяя причины там - либо по задаче, либо путем проверки AggregateException.

+0

Еще маленький вопрос. Когда я не использую это решение в цикле for или что-то в этом роде, но настройте тест внутри кода следующим образом: ct.ThrowIfCancellationRequested(); Никакое исключение, похоже, не выбрасывается ... это правильно? – user369122

+0

@ user369122 Если вы не в цикле, возможно, что он прошел проверку перед отменой ...? –

+0

нет нет. Я действительно сделал что-то вроде этого (для теста): Thread.Sleep (10000); if (ct.IsCancellationRequested) { ct.ThrowIfCancellationRequested(); } И я не так медленно ;-) Достигнута линия с броском. – user369122