正在捕获并行异常

时间:2012-07-25 04:47:43

标签: asynchronous task-parallel-library .net-4.5 async-await c#-5.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还是运行到完成代码。 关于我做错了什么的任何想法? 感谢

1 个答案:

答案 0 :(得分:1)

我认为RunAsyncProcessAsync相同。

  

取消令牌抛出异常,但根据intellitrace,它会在方法结束时被捕获。

烨。任何async方法都会捕获自己的异常,并将它们放在返回的Task上。这是设计的。

  

无论continuewith函数始终执行IsComleted还是运行完成代码。

好吧,让我们再看一下代码:

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

考虑传递给StartNew的lambda:它调用RunAsync,忽略它返回的Task,然后返回true(成功)。因此Task返回的StartNew将始终成功返回。这就是ContinueWith总是为成功完成的任务执行的原因。

您真正想要的是awaitTask返回的RunAsync。所以,像这样:

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

您仍然忽略RunAsync的返回值(忽略它返回的bool),但您不会忽略Task本身(包括取消/异常信息)

P.S。我假设有很多代码你没有向我们展示;使用StartNew / Run启动一些异步工作并返回一个值非常昂贵。

P.P.S。 Use await Task.Delay instead of Thread.Sleep