c# - 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?
解决方案
好的,感谢@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 线程)。因此,如果有人可以弥补我的答案,那就太好了。
无论如何,在将表单创建移到对异步方法的调用下方之后,一切都开始工作了。
推荐阅读
- c++ - 在 C++ 中打印和替换数字和百分比
- c++ - Google Benchmark:相同的功能,不同的数据
- javascript - 状态的变化不会反映在组件中,状态应该返回一个数组但返回一个空对象
- r - 将 data.table/data.frame 与部分匹配的矩阵匹配
- android - C/C++ android 11 代码在 strstr api 调用时崩溃
- textx - 如何让 textX 语法识别普通字符串和特殊关键字
- dictionary - 定义此嵌套映射时如何避免重复
- python - Bash:[psql] [python] [python3] [pip]:找不到命令(类似的问题不解决)
- ubuntu - 我无法将 XRDP 配置为重新连接到 Ubuntu 20 中的现有会话
- javascript - jQuery加载不起作用/第一次加载后按钮不可点击