1
我從System.Net.HttpClient
類派生實現處理令牌檢索和重新搜索的客戶端。客戶端使用所有必需的驗證參數進行初始化,並可能同時使用。在這種情況下,我需要防止客戶端請求多個令牌(針對不同的請求)。在異步方法中使用信號量會導致WPF調度程序線程死鎖嗎?
我不知道我的代碼是否會導致一個WPF應用程序死鎖如果用戶啓動調度線程上多個Web請求(因爲信號量是不可重入的,所以調度線程可能在等待被阻止在信號量上,並且如果分派器線程被阻塞,原始任務可能無法完成)。
public class ApiClient : HttpClient
{
public override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (_token == null)
{
await _semaphore.WaitAsync(cancellationToken);
try
{
if (_token == null)
{
// _token = await _tokenService.AcquireToken(xx,xx,xx);
}
}
finally
{
_semaphore.Release();
}
}
else if (_token.IsExpired)
{
await _semaphore.WaitAsync(cancellationToken);
try
{
if (_token.IsExpired)
{
// _token = await _tokenService.RefreshToken(xx,xx,xx);
}
}
finally
{
_semaphore.Release();
}
}
return await base.SendAsync(request, cancellationToken);
}
}
當有兩個線程彼此等待時發生死鎖。所以基本上,如果你的Dispatcher線程等待Api線程(實際上正在發生)和Api線程等待來自Dispatcher線程的響應(這不應該是這樣),那麼你將會遇到死鎖。我不明白爲什麼在你的場景中會發生死鎖。如果請求太多,最糟糕的情況是超時,有些則無法及時完成。 – 3615
但是,當使用信號量的同步Wait()方法時,我肯定會發生死鎖,是嗎? – Ehssan
我不這麼認爲。如果您將使用Wait()而不是WaitAsync(),則關於死鎖的情況不應改變,除非Api線程以某種隱藏方式嘗試訪問Dispatcher線程。不同之處在於線程使用率更低效:如果信號量已滿,ApplicationPool Task不會返回到池,但會被阻塞等待。因此,當下一個請求將驅動被阻塞的線程將無法提供請求並創建新的線程。所以你會得到更多的線程。 – 3615