首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >异步死锁-非标准死锁

异步死锁-非标准死锁
EN

Stack Overflow用户
提问于 2018-05-24 18:00:48
回答 1查看 68关注 0票数 0

我调用异步方法和一些死锁。现在我完全不知道为什么会发生这种事。我不认为这是一个标准的死锁,因为我在Main方法中调用Task.Result,而不是在UI线程中。此外,我还尝试在不调用Task的情况下使用async Main。但结果是一样的。

问题出在WinForms项目上。一切都从Main方法开始:

代码语言:javascript
复制
bool res = Task.Run(() => contr.RegisterPremiseAllInOne()).Result;

这是在新任务中对异步方法RegisterPremiseAllInOne的简单调用。

接下来会发生什么..。RegisterPremiseAllInOne的工作原理更像这样(简化模型):

代码语言:javascript
复制
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
}

现在我将向您展示每个方法的调用是做什么的(所有内容都以对WebApi的rest查询结束):

代码语言:javascript
复制
GetLoggedAppUser -> 
await API.Users.GetLoggedAppUser() -> 
await ClientHelper.GetObjectFromRequest<Appuser>("AppUsers/logged") -> 
await SendAsyncRequest() -> 
await HttpClient.SendAsync()

我希望这篇文章的可读性很好。

这条路运行得很好。有趣的是,GetPremisesForLoggedUserGetLoggedAppUser部分收敛,看起来像这样:

代码语言:javascript
复制
GetPremisesForLoggedUser -> 
await API.Premises.GetForLoggedUser() -> 
await ClientHelper.GetListFromRequest<premise>("premises/logged") -> 
await SendAsyncRequest() -> 
await HttpClient.SendAsync()

如你所见,这里有一条笔直的小路。调用API并最终发送http请求。

来自HttpClientSendAsync中存在死锁。我不知道为什么。然而,第一条路径运行得很好。

在服务器端,一切都很好。服务端返回成功响应。但是客户端挂了。

我觉得应该能行得通。我不会把synchronious和async代码混在一起。所有方法都返回Task<T>并标记为async。

也许有人知道问题出在哪里?也许你想看看调试窗口中的一些截图:并行堆栈/任务?

EN

回答 1

Stack Overflow用户

发布于 2018-05-24 20:24:49

好了,多亏了@usr和@Evk,我找到了bug。然而,这是标准的UI死锁,但更多的是伪装。

在我调用GetPremisesForLoggedUser()之前,我使用工厂(IoC容器)创建了一个表单:

代码语言:javascript
复制
IPremisePickerView view = objFactory.Resolve<IPremisePickerView>();
var premises = await GetPremisesForLoggedUser();

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

所以我调用的是await GetPremisesForLoggedUser()

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

无论如何,在将表单创建移至async方法调用下面之后,一切都开始工作了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50506428

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档