![](/img/trans.png)
[英]How does SemaphoreSlim.WaitAsync allow for sequential executions of an async function?
[英]How to cancel SemaphoreSlim WaitAsync method
考慮以下使用.NET 5
執行的代碼:
using System;
using System.Threading;
public class Program
{
public static void Main(string[] args)
{
var semaphore = new SemaphoreSlim(0);
var cts = new CancellationTokenSource();
var entrance = semaphore.WaitAsync(cts.Token);
cts.Cancel();
cts.Dispose();
semaphore.Release();
Console.WriteLine("Entrance status: " + entrance.Status);
Console.WriteLine("Current count: " + semaphore.CurrentCount);
}
}
當我運行此代碼時,應用程序成功完成並得到以下結果:
進入狀態:WaitingForActivation
當前計數:0
但是因為我在釋放信號量之前取消了WaitAsync
操作,所以我期望信號量CurrentCount
為1
並且Task
處於Canceled
狀態。
在發布問題之前,我在https://dotnetfiddle.net 中運行了代碼,令人驚訝的是,它在.NET Framework 4.7.2
按預期運行。
我是否在 .NET 5 SemaphoreSlim
發現了一個錯誤?
有沒有辦法在.NET 5
獲得以前的行為?
PS:我找到了一種通過為WaitAsync
操作設置超時來獲得前一種行為的WaitAsync
,但這不是我認為可以接受的答案。
根據 Guru Stron 評論進行編輯
正如我所料,在Release
語句之前等待entrance
會產生一個OperationCancelledException
。
但是在語句之后等待不會拋出任何異常並且信號量被“消耗”。
兩種情況都會在以前的.NET Framework
產生錯誤。
CancellationTokenSource.Cancel
是取消請求。 該取消標記將被立即取消,但Cancel
並不保證等待,阻止當前線程,直到聽到取消所有操作令牌都被取消(和他們的父母操作等)。
換句話說,您的代碼具有固有的競爭條件:是否Release
或CancellationToken
的取消將首先到達WaitAsync
操作。 如果Release
首先到達它,則將獲取信號量。 如果取消首先到達它,則等待將被取消。
在調用Release
之前await
WaitAsync
操作的任務通過 (a) 等待操作解決此競爭條件,強制它在發送Release
之前看到取消。
我是否在 .NET 5 SemaphoreSlim 中發現了錯誤?
否。代碼取決於 .NET Framework 和 .NET 5 上的競爭條件。不保證競爭條件的結果在任一平台上都有任何特定結果。
有沒有辦法在 .NET 5 中獲得以前的行為?
不。我建議重新編寫代碼,使其不依賴於競爭條件。 然后它將在兩個平台上正常工作。
代碼可能將SemaphoreSlim
用於它不是為之設計的東西。 例如,如果您需要一個異步工作隊列,則構建一個異步工作隊列,而不是嘗試將SemaphoreSlim
用作一個隊列。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.