簡體   English   中英

如何取消 SemaphoreSlim WaitAsync 方法

[英]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操作,所以我期望信號量CurrentCount1並且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並不保證等待,阻止當前線程,直到聽到取消所有操作令牌都被取消(和他們的父母操作等)。

換句話說,您的代碼具有固有的競爭條件:是否ReleaseCancellationToken的取消將首先到達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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM