2016-10-14 10 views
-1

このコードでは、Start関数を起動した後、バインドされた「キャンセル」ボタンを使用してタスクを停止しようとしましたが、処理されなかったことを示す 'System.OperationCanceledException'ユーザーコードで...なぜ私のtry catchブロックでThrowIfCancellationRequestedが処理されないのですか?

なぜ私のTryキャッチブロックはそれを処理しませんか?どのように私のビュー内の "キャンセル"ボタンからそのタスクを停止することができますか?

namespace LauncherWPF.ViewModel 
{ 
    /// <summary> 
    /// This class contLineageViewModel ains properties that a View can data bind to. 
    /// </summary> 
    public class : ViewModelBase 
    { 
     private CancellationTokenSource _tokenSource; 
     private CancellationToken _cancellationToken; 

     /// <summary> 
     /// Initializes a new instance of the LineageViewModel class. 
     /// </summary> 
     public LineageViewModel() 
     {     
     } 

     public void Start() 
     { 

      _tokenSource = new CancellationTokenSource(); 
      _cancellationToken = _tokenSource.Token; 

      Debug.Write("TaskStarted"); 

      try 
      { 
       Task.Run(() => 
       { 
        for (var i = 0; i < 100; ++i) 
        { 
         _cancellationToken.ThrowIfCancellationRequested(); 
         Debug.Write("Progress " + i); 
         for (var j = 0; j < 100; ++j) 
         { 
          Debug.Write("Updated " + j); 
          Thread.Sleep(50); 
         } 
        } 
       }, _cancellationToken); 
      } 
      catch (OperationCanceledException e) 
      { 
       Debug.Write("Canceled"); 
      } 
     } 

     public void Cancel() 
     { 
      //not working 
      _tokenSource.Cancel(); 

     } 
    } 
} 
+0

はhttps://stackoverflow.com/questions/28629405/exception-in-async-methods-is-not-caught –

+0

申し訳ありませんが、私は私の問題とは知らなかったも参照してください。非同期タスクに関連していたので、適切な用語で検索することができませんでした...だから、私はこの質問を作成しました。気をつけて投票してください... – exSnake

答えて

0

あなたはtry/catchブロックを終了した後にタスクが非同期で実行されるため。

代わりにこれを試してみてください:

Task.Run(() => 
{ 
    try 
    { 
    for (var i = 0; i < 100; ++i) 
    { 
     _cancellationToken.ThrowIfCancellationRequested(); 
     Debug.Write("Progress " + i); 
     for (var j = 0; j < 100; ++j) 
     { 
      Debug.Write("Updated " + j); 
      Thread.Sleep(50); 
     } 
    } 
    } 
    catch (OperationCanceledException e) 
    { 
     Debug.Write("Canceled"); 
    } 
}, _cancellationToken); 

はさらに良いことに、通常の流れの例外に依存しないでください。あなたは簡単のように書き換えることができます:

if(_cancellationToken.IsCancellationRequested) 
{ 
    Console.WriteLine("cancelled"); 
    break; 
} 
+0

それを処理する権利は、キャンセルが要求されたかどうかを確認することだけです。 – exSnake

+0

例外は多くの費用がかかります。プロパティのチェックは行いません。例外は、通常の実行の一部ではなく、例外的な場合にのみ使用する必要があります。 – spender

+1

_ "通常のフローの例外には依存しない" _ - それは良いアドバイスです。それ以外はここには適用されません。タスクのキャンセルは「通常のフロー」ではなく、TPLは特に 'TaskCanceledException'と連携して動作するように設計されています。例外がなければ、 'Task'オブジェクト自体は' Canceled'状態に置かれる代わりに、正常に完了します。いくつかのコードではこれは問題ありませんが、 'Task'が正常に完了したかどうかを知ることが大切です(タスクをキャンセルしようとすると、レースのためにあなたにそれが伝わらないでしょう)。それは終わった。 –

関連する問題