首页 > 解决方案 > Deadlocked with async - not standard deadlock

问题描述

I call aynchronious methods and something deadlocks. Now I don't have any idea why this is happening. I don't think that this is a standard deadlock, because I call Task.Result in Main method - NOT IN UI thread. What's more, I also tried using async Main without any calls to Task. But the result is the same.

Problem is with WinForms project. Everything starts in Main method:

bool res = Task.Run(() => contr.RegisterPremiseAllInOne()).Result;

This is imple call to asynchronious method RegisterPremiseAllInOne in new Task.

What happens next... RegisterPremiseAllInOne works more-like like that (simplified model):

public async Task<bool> RegisterPremiseAllInOne()
{
   AppUser loggedAppUser = await appUserContr.GetLoggedAppUser(); // <-- everything works fine here
   if(loggedAppUser == null)
      return false;

   var premises = await GetPremisesForLoggedUser(); //at the end there is a deadlock
}

I will show you now what calls does each and every method do (everything ends up with rest queries to WebApi):

GetLoggedAppUser -> 
await API.Users.GetLoggedAppUser() -> 
await ClientHelper.GetObjectFromRequest<Appuser>("AppUsers/logged") -> 
await SendAsyncRequest() -> 
await HttpClient.SendAsync()

I hope this is quite readable.

This path works well. What's interesting, GetPremisesForLoggedUser is partially convergent with GetLoggedAppUser and looks like that:

GetPremisesForLoggedUser -> 
await API.Premises.GetForLoggedUser() -> 
await ClientHelper.GetListFromRequest<premise>("premises/logged") -> 
await SendAsyncRequest() -> 
await HttpClient.SendAsync()

As you can see there is a straight path. Call to API and eventually sending a http request.

Deadlock is within SendAsync from HttpClient. I don't have any idea why. Yet the first path works fine.

On the server side everything fine as well. Server returns successful response. But the client hangs.

I think it should work. I don't mix synchronious with async code. All the methods return Task<T> and are marked as async.

Maybe someone know where the problem may exists? Maybe you will want to see some screenshots from debug windows: Parallel Stack / Tasks?

标签: c#asynchronousdeadlock

解决方案


好的,感谢@usr 和@Evk,我发现了这个错误。然而,它是标准的 UI 死锁,但没有更多的伪装。

就在我打电话之前,我正在GetPremisesForLoggedUser()使用工厂(IoC 容器)创建一个表单:

IPremisePickerView view = objFactory.Resolve<IPremisePickerView>();
var premises = await GetPremisesForLoggedUser();

创建表单时,该表单所属的线程自动成为 UI 线程。我认为这是在 Form 类中完成的。

所以事实证明我正在调用 await GetPremisesForLoggedUser()

在 UI 线程上。所以可能所有的任务都开始在 UI 线程上运行(从某个点)。但这是否意味着 Main 中调用的 Task.Run.Result 阻塞了等待结果的 UI 线程?我不确定,因为这是在主线程上调用的(在这种情况下不是 UI 线程)。因此,如果有人可以弥补我的答案,那就太好了。

无论如何,在将表单创建移到对异步方法的调用下方之后,一切都开始工作了。


推荐阅读