【发布时间】:2021-12-22 12:48:47
【问题描述】:
考虑以下代码,使用.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 操作的超时来获得前一种行为,但这不是我认为可以接受的答案。
根据 Guru Stron cmets 进行编辑
在Release 语句生成OperationCancelledException 之前等待entrance,正如我所期望的那样。
但是在语句之后等待不会抛出任何异常并且信号量被“消耗”了。
这两种情况都会在以前的.NET Framework 中产生错误。
【问题讨论】:
-
如果您在
Release语句之后添加Console.WriteLine("Entrance status: " + entrance.Status);,它将报告Canceled状态。 -
等待任务也会抛出预期的错误。之后
Status也更改为预期。 -
@GuruStron:我在发布之前经常更改代码,以至于我犯了一个错误。在
Release语句之前等待将按预期生成OperationCancelledException,但在之后等待将成功完成。 -
我希望这两种情况都会导致
OperationCancelledException,就像在 .NET 4.7.2 中一样。 -
是的,也可以在 .NET 6 rc 中进行复制。检查状态两次使其成为需要的一次))
标签: c# .net-5 cancellationtokensource