某种程度上,我的异常似乎被他们正在执行的方法捕获。这是调用该方法的代码。如您所见,我创建了一个带有超时的取消令牌。我注册了一个方法,当取消令牌触发时调用,然后我开始一个新的任务。取消令牌似乎正常工作。和注册的方法一样。
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还是运行到完成代码。 关于我做错了什么的任何想法? 感谢
答案 0 :(得分:1)
我认为RunAsync
与ProcessAsync
相同。
取消令牌抛出异常,但根据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
总是为成功完成的任务执行的原因。
您真正想要的是await
由Task
返回的RunAsync
。所以,像这样:
var task = Task.Run(async () =>
{
await subscriber.RunAsync((T)messagePacket.Body, cancellationToken);
return true;
})
.ContinueWith(
您仍然忽略RunAsync
的返回值(忽略它返回的bool
),但您不会忽略Task
本身(包括取消/异常信息)
P.S。我假设有很多代码你没有向我们展示;使用StartNew
/ Run
启动一些异步工作并返回一个值非常昂贵。