为什么Task.WaitAll()不能阻止或这里导致死锁? [英] Why does Task.WaitAll() not block or cause a deadlock here?

查看:2195
本文介绍了为什么Task.WaitAll()不能阻止或这里导致死锁?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在以下两个等待例子通话使用。为了获得性能,样品被转换 Task.WaitAll()代替(不是真正的快,但是这仅仅是一个例子)。

In the example below two await calls are used. To gain performance, the sample gets converted Task.WaitAll() instead (not really any faster, but this is just an example).

这是code使用Sqlite.Net在Android库和方法从 OnResume()主UI线程名为:

This is code from a library using Sqlite.Net on Android and the method gets called from OnResume() on the main UI thread:

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线程上调用什么?

But from my understanding Task.WaitAll() should block the UI thread while waiting, thus leading to a deadlock. But it works just fine. Is that because the two calls don't actually invoke anything on the UI thread?

有什么区别,如果我使用 Task.WhenAll()呢?我想它,它会工作,即使在UI线程会被调用,就像等待

What's the difference if I use Task.WhenAll() instead? My guess it that it would work even if the UI thread would be invoked, just like with await.

推荐答案

我描述的僵局情况详细信息在我的博客。我也有的SynchronizationContext MSDN文章>你有帮助的。

I describe the details of the deadlock situation on my blog. I also have an MSDN article on SynchronizationContext that you may find helpful.

总之, Task.WaitAll 将在您的情况僵局,但只有当任务需要同步回UI线程才能完成。可以得出结论, CreateTableAsync&LT; T&GT;()不同步回UI线程

In summary, Task.WaitAll will deadlock in your scenario, but only if the tasks need to sync back to the UI thread in order to complete. You can conclude that CreateTableAsync<T>() does not sync back to the UI thread.

在此相反,这code就会死锁:

In contrast, this code will deadlock:

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

Task.WaitAll(SetupDatabaseAsync());

我建议你的的异步code座;在异步的世界里,后再同步回上下文是的默认的行为(如我描述了我的 异步介绍),所以很容易意外地做到这一点。在未来的一些改动Sqlite.Net可能(意外)同步回原来的上下文,然后使用任何code Task.WaitAll 喜欢你原来的例子会突然僵局。

I recommend that you not block on asynchronous code; in the async world, sync'ing back to the context is the default behavior (as I describe in my async intro), so it's easy to accidentally do it. Some changes to Sqlite.Net in the future may (accidentally) sync back to the original context, and then any code using Task.WaitAll like your original example will suddenly deadlock.

这是最好使用异步一路:

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

异步一路是的,我建议在我的异步最佳实践的文章

这篇关于为什么Task.WaitAll()不能阻止或这里导致死锁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆