0

どういうわけか、例外が実行されているメソッドによってキャッチされているようです。メソッドを呼び出すコードは次のとおりです。ご覧のとおり、タイムアウト付きのキャンセル トークンを作成します。キャンセル トークンが発生したときに呼び出すメソッドを登録してから、新しいタスクを開始します。キャンセル トークンは正常に機能しているようです。登録されたメソッドも同様です。

var cancellationToken = new CancellationTokenSource(subscriber.TimeToExpire).Token;
cancellationToken.Register(() =>
{
    subscriber.Abort();
});
var task = Task<bool>.Factory.StartNew(() =>
{                  
 subscriber.RunAsync((T)messagePacket.Body, cancellationToken);
 return true;
})
.ContinueWith(anticedant => 
{
    if (anticedant.IsCanceled)
    {
        Counter.Increment(12);
        Trace.WriteLine("Request was canceled");
    }

    if (anticedant.IsFaulted)
    {
        Counter.Increment(13);
        Trace.WriteLine("Request was canceled");
    }

    if (anticedant.IsCompleted)
    {
        Counter.Increment(14);
    }

次のコードは、例外をスローするだけでなく、例外をキャッチしているように見えるメソッドです。

public async override Task<bool> ProcessAsync(Message input, CancellationToken cancellationToken)
{
    Random r = new Random();
    Thread.Sleep(r.Next(90, 110));
    cancellationToken.ThrowIfCancellationRequested();
    return await DoSomethingAsync(input);
}

キャンセルトークンによって例外がスローされていますが、intellitrace によると、メソッドの最後でキャッチされています。独自の例外をスローするなど、さまざまなオプションを試しましたが、 continuewith 関数が常に IsComleted を実行するか、完了コードまで実行されます。私が間違っていることについてのアイデアはありますか? ありがとう

4

1 に答える 1

1

RunAsyncと同じだと思いProcessAsyncます。

キャンセルトークンによって例外がスローされていますが、intellitrace によると、メソッドの最後でキャッチされています。

うん。どのasyncメソッドも独自の例外をキャッチし、返された に配置しますTask。これは仕様によるものです。

continuewith 関数は常に IsComleted または完了コードを実行します。

さて、コードをもう一度見てみましょう。

var task = Task<bool>.Factory.StartNew(() =>
{                  
  subscriber.RunAsync((T)messagePacket.Body, cancellationToken);
  return true;
})
.ContinueWith(

に渡されたラムダを考えてみましょうStartNew。これは を呼び出しRunAsync、返される を無視してから(正常に)Task返されます。trueしたがって、Task返された byStartNewは常に正常に返されます。これがContinueWith、正常に完了したタスクに対して常に実行される理由です。

あなたが本当に欲しいのは、awaitによってTask返されることRunAsyncです。したがって、次のようなものです。

var task = Task.Run(async () =>
{                  
  await subscriber.RunAsync((T)messagePacket.Body, cancellationToken);
  return true;
})
.ContinueWith(

あなたはまだ戻り値を無視していますがRunAsyncboolそれが返すものは無視されます)、それ自体を無視していませんTask(キャンセル/例外情報を含む)。

PS あなたが私たちに見せていないコードがたくさんあると思います。StartNew/を使用Runして非同期作業を開始し、値を返すだけでは非常にコストがかかります。

PPSの代わりに使用await Task.DelayThread.Sleepします。

于 2012-07-25T15:35:25.743 に答える