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

我认为这RunAsyncProcessAsync.

取消令牌引发了异常,但根据 Intellitrace,它在方法结束时被捕获。

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

不管 continuewith 函数总是执行 IsComleted 或运行到完成代码。

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

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

考虑传递给 的 lambda StartNew:它调用RunAsync,它忽略Task它返回的 ,然后它返回true(成功)。所以Task返回的StartNew人总是会成功返回。这就是为什么ContinueWith总是为成功完成的任务执行。

你真正想要的是await返回TaskRunAsync. 所以,像这样:

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

您仍然忽略RunAsyncbool它返回被忽略)的返回值,但您并没有忽略它Task本身(包括取消/异常信息)。

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

PPS使用await Task.Delay而不是Thread.Sleep.

于 2012-07-25T15:35:25.743 回答