首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TaskCanceledException与ContinueWith

TaskCanceledException与ContinueWith
EN

Stack Overflow用户
提问于 2015-02-20 16:38:32
回答 3查看 1.8K关注 0票数 9

我一直在试图弄清楚为什么我要为最近开始出错的异步代码获得一个TaskCanceledException。我已经将我的问题简化为一个小代码片段,它让我抓挠我的头:

代码语言:javascript
复制
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,我不知道它是从哪里来的!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-02-20 16:46:41

您使用的是错误的task接触式选项:

请参阅以下链接:https://msdn.microsoft.com/en-us/library/system.threading.tasks.taskcontinuationoptions%28v=vs.110%29.aspx

它说:指定只有在先前抛出一个未处理的异常时,才应该对延续任务进行调度。此选项对多任务延续无效。

票数 2
EN

Stack Overflow用户

发布于 2019-10-20 00:52:17

正如上面所述,此调用只需要处于故障状态的前置任务,否则将引发TaskCanceledException,对于这种具体情况,您可以泛化ContinueWith以处理所有状态:

代码语言:javascript
复制
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'
        });
票数 2
EN

Stack Overflow用户

发布于 2022-08-30 09:43:09

我还收到了以下错误:

代码块如下所示:

代码语言:javascript
复制
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

我所做的就是将代码修改为:

代码语言:javascript
复制
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(...),而是用一个常规的尝试-捕捉块来代替它,以防我感兴趣的任务失败。我认为这简化了代码,并使其更具可读性。

在问题中,有这一行代码:

代码语言:javascript
复制
Task.Delay(1000).ContinueWith(t => Console.WriteLine("{0}", t.Exception), TaskContinuationOptions.OnlyOnFaulted).Wait();

我会把它改写成:

代码语言:javascript
复制
try
{
    Task.Delay(1000).Wait();
}
catch (Exception ex)
{
    Console.WriteLine("{0}", ex);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28633871

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档