【问题标题】:Task.Run freezingTask.Run 冻结
【发布时间】:2013-04-05 05:24:13
【问题描述】:

谁能告诉我为什么在完成 lambda 后会冻结:

        return await Task.Run(() =>
        {
            return SuperLongMethod();
        })

...但以下内容按预期工作:

        return Task.Run(() =>
        {
            return SuperLongMethod();
        }).GetAwaiter().GetResult();

第一个版本中的 Task.Run 似乎无法识别 lambda 已完成。我的代码中有其他示例,我使用第一个版本没有问题,所以我不知道有什么区别。

为清楚起见,SuperLongMethod() 调用 Web 服务并对结果数据进行大量后处理

【问题讨论】:

    标签: c# task-parallel-library .net-4.5 async-await c#-5.0


    【解决方案1】:

    我猜想在调用堆栈的更深处,您正在调用Task.WaitTask<T>.Result,从而导致the deadlock issue I describe on my blog。你应该改用await

    作为旁注,SuperLongMethod 可能应该分解为 CallWebServiceAsyncDoPostProcessing,并且只有 DoPostProcessing 应该包含在 Task.Run 中。

    【讨论】:

    • 您的博客本质上说要远离等待任务,这是解决这种令人困惑的死锁的方法,但我使用 Task.Run 的原因是为了有效地将处理强制到另一个线程上,所以GUI 保持流畅。否则,在后处理开始时它会受到打击。但是,您的博客建议在 Task.Run 上使用 ConfigureAwait(false) 效果很好:)
    • 我还应该补充一点,我的第二个示例代码块实际上是阻塞的,所以这不是我认为的解决方法
    • 其实我的博文推荐等待任务;它不鼓励阻塞任务。 ConfigureAwait 工作的事实向我表明您的代码仍然不正确 - 进一步提升您的调用堆栈您仍然阻塞从该 async 方法返回的任务。
    • 我的 GUI 直接用 await 调用我的异步函数。在我的函数中,Task.Run 执行并阻塞,但 GUI 保持响应。当 Task.Run 完成时,它会因为您建议的 ConfigureAwait(false) 而继续,而在没有它之前,它会死锁。我不认为这种方法是错误的,除非您觉得可能存在不一致。
    • 我仍然无法清楚地了解您的代码,但感觉确实有问题(ConfigureAwait 应该没有必要)。如果你发布你的代码,我会看看。
    猜你喜欢
    • 2015-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-24
    • 2011-10-24
    • 2015-11-17
    • 1970-01-01
    相关资源
    最近更新 更多