【问题标题】:Task.Wait Deadlocks on a Task returned by Task.RunTask.Run 返回的任务上的 Task.Wait 死锁
【发布时间】:2013-08-22 16:55:14
【问题描述】:

我在 4.5 中遇到了一些异步代码的死锁问题。我读了Stephen Cleary's blog about preventing deadlocks that occur when the task captures the executing context 然后在相同的上下文中你通过等待任务来阻止。我试图实施该解决方案,但我仍然遇到死锁,我不明白为什么。

原始代码

消费类:

private void Update(...)
    {
        //... do some stuff ... 
        _repository.Save(listing).Wait();
    }

返回任务的类:

protected override Task Save(...)
    {
        return Task.Run(() =>
        {
            ... do some stuff ...
            _logger.Debug("All Done!!!");
        });
    }

修改后的代码

消费类:

private void Update(...)
    {
        //... do some stuff ... 
        _repository.Save(listing).Wait();
    }

返回任务的类:

protected override async Task Save(...)
    {
        await Task.Run(() =>
        {
            ... do some stuff ...
            _logger.Debug("All Done!!!");
        }).ConfigureAwait(false);
    }

即使在修改后的版本中,我明确告诉等待的任务不要绑定到上下文,我仍然会遇到死锁。

有什么想法吗?

【问题讨论】:

  • ConfigureAwait 只是当您不能使用await 时的一种解决方法。最好的解决方案肯定是让Update 成为async Task 方法;有什么理由这行不通吗?
  • 看起来Save 需要await 而你的lambda Task 需要async
  • 我的 Update 方法是一个 WebApi IHttpController。让控制器返回异步无效或异步任务会更好吗?感谢斯蒂芬的快速回复
  • 没关系,我看到你的博客给出了一个返回异步任务的控制器方法示例
  • 让我担心的是,我们实际上还有其他代码在使用同一个存储库。Save 方法然后调用 .Wait,但其他代码没有死锁,也没有标记为异步。我在我们的代码库中进行了搜索,我们到处都有数百个 .Wait 调用,但这是我们第一次看到死锁。我正在尝试尽可能多地了解这个问题,以防我们开始在其他地方看到它。

标签: c# .net asynchronous .net-4.5 async-await


【解决方案1】:

尝试正常的异步等待模式

private async void Update(...)
{
    //... do some stuff ... 
   await _repository.Save(listing);
}

protected override async Task Save(...)
{

        ... do some stuff ...
        _logger.Debug("All Done!!!");
}

【讨论】:

  • 我知道这已经很老了,但是在更新中,异步 void 使得很难很好地捕获异常,如果可能的话使用异步任务?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-03
  • 2017-09-25
  • 2018-02-13
相关资源
最近更新 更多