为什么Task.WaitAll()在这里不会阻止或导致死锁?

克鲁梅鲁尔

在下面的示例中await,使用了两个调用。为了获得性能,示例将转换为示例Task.WaitAll()(并非真的更快,但这只是一个示例)。

这是在Android上使用Sqlite.Net的库中的代码,该方法OnResume()在主UI线程上调用

public async Task SetupDatabaseAsync()
{
  await CreateTableAsync<Session>();
  await CreateTableAsync<Speaker>();
}

这是替代方法:

public void SetupDatabaseAsync()
{
  var t1 = CreateTableAsync<Session>();
  var t2 = CreateTableAsync<Speaker>();

  Task.WaitAll(t1, t2);
}

但是据我了解,Task.WaitAll()应该在等待时阻塞UI线程,从而导致死锁。但这很好。那是因为这两个调用实际上并未在UI线程上调用任何东西吗?

如果我改用有什么区别Task.WhenAll()我猜想,即使将调用UI线程也可以正常工作,就像使用一样await

斯蒂芬·克莱里

在博客上描述了僵局情况细节我也有一篇MSDN文章SynchronizationContext,您可能会有所帮助。

总之,Task.WaitAll将在您的方案中陷入僵局,但前提是任务需要同步回UI线程才能完成。您可以得出结论,CreateTableAsync<T>()它不同步回UI线程。

相反,此代码将陷入僵局:

public async Task SetupDatabaseAsync()
{
  await CreateTableAsync<Session>();
  await CreateTableAsync<Speaker>();
}

Task.WaitAll(SetupDatabaseAsync());

我建议您不要阻塞异步代码。async世界上,同步返回到上下文是默认行为(正如我在async介绍中所描述的),因此很容易意外地做到这一点。将来对Sqlite.Net的某些更改可能会(偶然)同步回原始上下文,然后使用Task.WaitAll类似原始示例的任何代码都会突然死锁。

最好async一路使用

public Task SetupDatabaseAsync()
{
  var t1 = CreateTableAsync<Session>();
  var t2 = CreateTableAsync<Speaker>();
  return Task.WhenAll(t1, t2);
}

“一路异步”是我在异步最佳实践文章中推荐的准则之一

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么在这里使用两个ManualResetEvents会导致死锁?

来自分类Dev

为什么不会 for ... 在这里循环?

来自分类Dev

为什么Task.WhenAll()在这里阻塞?

来自分类Dev

为什么在这里使用进程替换导致挂起?

来自分类Dev

为什么我们在这里没有死锁?

来自分类Dev

为什么在这里不确定?

来自分类Dev

为什么在这里的盒子?

来自分类Dev

为什么WlanOpenHandle()在这里失败?

来自分类Dev

为什么在这里发生僵局

来自分类Dev

为什么在这里使用锁?

来自分类Dev

为什么$ .isEmptyObject在这里无效

来自分类Dev

为什么python在这里运行?

来自分类Dev

为什么使用原子在这里?

来自分类Dev

为什么在这里需要'break;'?

来自分类Dev

为什么WlanOpenHandle()在这里失败?

来自分类Dev

为什么在这里抛出异常?

来自分类Dev

为什么$ .isEmptyObject在这里无效

来自分类Dev

为什么在这里得到NullPointerException?

来自分类Dev

为什么python在这里运行?

来自分类Dev

为什么在使用默认的prepare_arch_switch()时schedule()不会导致死锁

来自分类Dev

为什么在这里调用keyup处理程序,我可以阻止它吗?

来自分类Dev

为什么我在这里得到期望的对/错,而不是列表或阻止?

来自分类Dev

为什么星火据帧缓存不会在这里工作

来自分类Dev

为什么Python的unittest.assertRaises()不会在这里引发错误?

来自分类Dev

为什么pthread_cond_signal导致死锁

来自分类Dev

为什么pthread_cond_signal导致死锁

来自分类Dev

为什么awk在这里什么也不做?

来自分类Dev

逗号在这里有什么功能,为什么它不会引起编译时错误?

来自分类Dev

为什么在这里进行收益优化

Related 相关文章

热门标签

归档