![](/img/trans.png)
[英]Can async/await still deadlock if ConfigureAwait(false) is used?
[英]Still confused on ConfigureAwait(false) used with GetAwaiter and GetResult in C#. Getting a deadlock or method not returning
我已經讀過: http : //blog.stephencleary.com/2012/07/dont-block-on-async-code.html和死鎖的公認答案, 即使在Asp.Net流中使用ConfigureAwait(false)之后,也只是太稠密,看不到發生了什么事。
我有代碼:
private void CancelCalibration()
{
// ...
TaskResult closeDoorResult = CloseLoadDoor().ConfigureAwait(false).GetAwaiter().GetResult();
CalibrationState = CalibrationState.Idle;
return;
// ...
}
private async Task<TaskResult> CloseLoadDoor()
{
TaskResult result = await _model.CloseLoadDoor().ConfigureAwait(false);
return result;
}
public async Task<TaskResult> CloseLoadDoor()
{
TaskResult result = new TaskResult()
{
Explanation = "",
Success = true
};
await _robotController.CloseLoadDoors().ConfigureAwait(false);
return result;
}
public async Task CloseLoadDoors()
{
await Task.Run(() => _robot.CloseLoadDoors());
}
public void CloseLoadDoors()
{
// syncronous code from here down
_doorController.CloseLoadDoors(_operationsManager.GetLoadDoorCalibration());
}
如您所見,CloseLoadDoor被聲明為異步。 我以為(特別是從以上第一篇文章中)我可以通過使用ConfigureAwait(false)來調用一個沒有死鎖的異步方法。 但這就是我似乎得到的。 對“ CloseLoadDoor()。ConfigureAwait(false).GetAwaiter()。GetResult()的調用永遠不會返回!
我正在使用GetAwaiter.GetResult,因為CancelCalibration不是異步方法。 它是通過MVVM模式定義的按鈕處理程序:
public ICommand CancelCalibrationCommand
=> _cancelCalibrationCommand ?? (_cancelCalibrationCommand = new DelegateCommand(CancelCalibration));
如果有人要告訴我可以使CancelCalibration異步,請告訴我如何。 我可以將async
添加到方法聲明中嗎? 但是,我仍然想知道為什么ConfigureAwait.GetAwaiter.GetResult
模式給我帶來麻煩。 我的理解是,當不能選擇更改簽名時, GetAwaiter.GetResult
是一種從同步方法中調用異步方法的方法。
我猜我並沒有真正從使用原始上下文中解放出來,但是我在做錯什么,以及解決該問題的模式是什么? 謝謝戴夫
我以為(特別是從以上第一篇文章中)我可以通過使用ConfigureAwait(false)來調用一個沒有死鎖的異步方法。
那篇文章有一個重要的說明:
使用ConfigureAwait(false)避免死鎖是一種危險的做法。 在阻塞代碼調用的所有方法( 包括所有第三方代碼和第二方代碼 )的傳遞關閉中,您必須為每次等待使用ConfigureAwait(false)。 使用ConfigureAwait(false)避免死鎖充其量只是一種破解)。
那么,是否在傳遞閉包中為每個 await
使用ConfigureAwait(false)
? 這意味着:
CloseLoadDoor
是否每次await
都使用ConfigureAwait(false)
? 從發布的代碼中我們可以看到它確實如此。 _model.CloseLoadDoor
是否每次await
都使用ConfigureAwait(false)
? 我們看不到。 _model.CloseLoadDoor
調用的每個方法是否都為每次await
使用ConfigureAwait(false)
? _model.CloseLoadDoor
調用的每個方法調用的每個方法是否都對每次await
使用ConfigureAwait(false)
? 至少這是一個沉重的維護負擔。 我懷疑在調用堆棧的某個地方,缺少一個ConfigureAwait(false)
。
該注釋總結如下:
正如該帖子的標題所指出的那樣,更好的解決方案是“不要阻止異步代碼”。
換句話說,該文章的重點是“不要阻止異步代碼”。 這並不是說“使用這一巧妙技巧阻止異步代碼”。
如果您確實想擁有一個同時支持同步和異步調用者的API,建議在我關於brownfield async的文章中使用bool參數hack。
附帶說明一下,在代碼CloseLoadDoor().ConfigureAwait(false).GetAwaiter().GetResult()
, ConfigureAwait
不會執行任何操作。 它是“等待配置”,而不是“配置任務”。 由於那里沒有await
,因此ConfigureAwait(false)
無效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.