我一直在试图弄清楚为什么我要为最近开始出错的异步代码获得一个TaskCanceledException。我已经将我的问题简化为一个小代码片段,它让我抓挠我的头:
static void Main(string[] args)
{
RunTest();
}
private static void RunTest()
{
Task.Delay(1000).ContinueWith(t => Console.WriteLine("{0}", t.Exception), TaskContinuationOptions.OnlyOnFaulted).Wait();
}据我所知,这应该只是暂停一秒钟,然后关闭。ContinueWith不会被调用(这只适用于我的实际用例)。然而,相反,我得到了一个TaskCanceledException,我不知道它是从哪里来的!
发布于 2015-02-20 16:46:41
您使用的是错误的task接触式选项:
它说:指定只有在先前抛出一个未处理的异常时,才应该对延续任务进行调度。此选项对多任务延续无效。
发布于 2019-10-20 00:52:17
正如上面所述,此调用只需要处于故障状态的前置任务,否则将引发TaskCanceledException,对于这种具体情况,您可以泛化ContinueWith以处理所有状态:
await Task.Delay(1000).ContinueWith(
task =>
{
/* take into account that Canceled-task throw on next row the TaskCancelledException */
if (!task.IsFaulted) {
return;
}
Console.WriteLine("{0}", task.Exception);
// do smth like 'throw task.Exception.InnerException'
});发布于 2022-08-30 09:43:09
我还收到了以下错误:

代码块如下所示:
private void CallMediator<TRequest>(TRequest request) where TRequest : IRequest<Unit>
{
_ = Task.Run(async () =>
{
var mediator = _serviceScopeFactory.CreateScope().ServiceProvider.GetService<IMediator>()!;
await mediator.Send(request).ContinueWith(LogException, TaskContinuationOptions.OnlyOnFaulted);
});
}
private void LogException(Task task)
{
if (task.Exception != null)
{
_logger.LogError(task.Exception, "{ErrorMessage}", task.Exception.Message);
}
}阅读ContinueWith方法的文档时,它有以下注意事项:
在当前任务完成之前,将不会计划执行返回的任务。如果没有满足通过
continuationOptions参数指定的连续条件,则将取消延续任务,而不是计划的。
因此,对我来说,它被称为第一个任务(mediator.Send(request)),然后继续执行任务ContinueWith(...),这是Iawait编辑的任务。但是,由于在第一个任务中没有出现异常,第二个任务被取消。因此,在等待第二个任务时,它抛出了一个TaskCanceledException。
我所做的就是将代码修改为:
private void CallMediator<TRequest>(TRequest request) where TRequest : IRequest<Unit>
{
_ = Task.Run(async () =>
{
var mediator = _serviceScopeFactory.CreateScope().ServiceProvider.GetService<IMediator>()!;
try
{
_ = await mediator.Send(request);
}
catch (Exception ex)
{
_logger.LogError(ex, "{ErrorMessage}", ex.Message);
}
});
}我没有使用.ContinueWith(...),而是用一个常规的尝试-捕捉块来代替它,以防我感兴趣的任务失败。我认为这简化了代码,并使其更具可读性。
在问题中,有这一行代码:
Task.Delay(1000).ContinueWith(t => Console.WriteLine("{0}", t.Exception), TaskContinuationOptions.OnlyOnFaulted).Wait();我会把它改写成:
try
{
Task.Delay(1000).Wait();
}
catch (Exception ex)
{
Console.WriteLine("{0}", ex);
}https://stackoverflow.com/questions/28633871
复制相似问题