2011-07-13 7 views
5

キャンセルトークンを使用してタイムアウト(タイムアウトが終了する前に)を持つタスクをキャンセルすると、例外がスローされます。例:例外がスローされずにタイムアウトで待機しているタスクをキャンセルする方法

mytask.start(); 
bool didTaskRunInTime = mytask.wait(5 mins, _cancelToken); 

つまり、次のようには行けません。

//was the task cancelled 
if (_cancelToken.IsCancelRequested) 
{ 
    // log cancel from user to file etc 
} 

if (didTaskRunInTime) 
{ 
    int taskResult = myTask.Result; 
    // log result to file 
} 
else if (!_cancelToken.IsCancelRequested) 
{ 
    // Tell user task timed out , log a message etc 
} 

私はこのすべてをキャッチブロックで実行しなければならず、コードが乱雑になります。これを行う正しい方法は何ですか?

答えて

13

の配列でTask.WaitAnyと呼び出すことができます。ちょうどです。次に、タスクのステータスを処理できますが、メソッドは戻ります。サンプルコード:タスクにフォルトが発生した場合、あなたはそれが確定だ時に強打を行く、それを避けるために、例外を「観察」する必要があること

using System; 
using System.Threading; 
using System.Threading.Tasks; 

class Test 
{ 
    static void Main() 
    { 
     Task sleeper = Task.Factory.StartNew(() => Thread.Sleep(100000)); 

     int index = Task.WaitAny(new[] { sleeper }, 
           TimeSpan.FromSeconds(0.5)); 
     Console.WriteLine(index); // Prints -1, timeout 

     var cts = new CancellationTokenSource(); 

     // Just a simple wait of getting a cancellable task 
     Task cancellable = sleeper.ContinueWith(ignored => {}, cts.Token); 

     // It doesn't matter that we cancel before the wait 
     cts.Cancel(); 

     index = Task.WaitAny(new[] { cancellable }, 
          TimeSpan.FromSeconds(0.5)); 
     Console.WriteLine(index); // 0 - task 0 has completed (ish :) 
     Console.WriteLine(cancellable.Status); // Cancelled 
    } 
} 

注:)

+0

私はそれがスローされると思う、WaitAnyはすべての例外を集約します、あなたは例外をキャッチするためにwaitAny(そしておそらく他のものをキャンセルした後)を待つ必要があります。 – eFloh

+0

ジョンに感謝します。しかし、waitanyはタイムアウトを取らない。私はタイムアウト処理を必要とする長い実行エクスポートを持っています。 – Gullu

+0

@eFloh: 'WaitAll'は例外を集約します。 「WaitAny」はしません。サンプルコードを参照してください。 –

3

OperationCanceledException

try 
{   
    mytask.start(); 
    bool didTaskRunInTime = mytask.wait(5 mins, _cancelToken); 

    if (didTaskRunInTime) 
    { 
     int taskResult = myTask.Result; 
     //log result to file 
    } 
    else 
    { 
     // Tell user task timed out , log a message etc 
    } 
} 
catch (OperationCanceledException ex) 
{ 
    // log cancel from user to file et 
} 
を使用するようにしてください
+0

それは私が避けようとしていたものでしたが、私は選択肢がないかもしれません。私の推論は、誰かがcancelTokenを設定し、なぜこの例外がスローされるように設計されているのかを取り消そうとしている場合です。ありがとうVlad – Gullu

+0

ここで例外を使用する必要はありません - 私はtry/catchなしの例について私の答えを見てください。 –

関連する問題