Is it safe to dispose a SemaphoreSlim while waiting for pending operations to cancel?(在等待挂起的操作取消时处置SemaphoreSlim是否安全?)
问题描述
我不得不使用SemaphoreSlim来确保以单线程方式访问我的代码的某些部分,并希望确保我正确地处理了所有内容。假设我有以下类:
public class Foo
{
private readonly CancellationTokenSource _canceller = new CancellationTokenSource();
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);
~Foo()
{
Dispose(false);
GC.SuppressFinalize(this);
}
public void Dispose()
{
Dispose(true);
}
protected void Dispose(bool disposing)
{
if (_disposed)
return;
_canceller.Cancel();
if (_disposing)
_semaphore.Dispose();
_disposed = true;
}
public async Task ExecuteAsync()
{
try
{
await _semaphore.WaitAsync(_canceller.Token);
}
catch (OperationCanceledException)
{
throw new ObjectDisposedException(nameof(Foo), "Cannot execute on a Foo after it has been disposed");
}
try
{
// Critical section
}
finally
{
_semaphore.Release();
}
}
}
当我调用Dispose(true)
时,我实际上是一个接一个地执行以下行:
_canceller.Cancel();
_semaphore.Dispose();
我的问题是,当前等待临界区的任何其他线程/任务会发生什么情况?我是否可以保证他们总是首先看到取消,因此不会在处理信号量时出现问题?到目前为止,这还没有引起任何问题,但这并不意味着它是安全的。
推荐答案
documentation for SemaphoreSlim似乎对您的问题非常具体。
SemaphoreSlim的所有公共成员和受保护成员都是线程安全的,并且可以从多个线程并发使用,Dispose()除外,它必须在SemaphoreSlim上的所有其他操作完成后才能使用。
确保所有其他操作都已完成的唯一真正方法是确保所有任务都已完成,如文档中的示例所示。
public class Foo
{
private readonly List<Task> _semaphoreTasks = new list<Task>();
protected void Dispose(bool disposing)
{
if (_disposed)
return;
_canceller.Cancel();
if (_disposing)
{
Task.WaitAll(tasks);
_semaphore.Dispose();
}
_disposed = true;
}
public async Task ExecuteAsync()
{
try
{
var task = _semaphore.WaitAsync(_canceller.Token);
_semaphoreTasks.Add(task);
await task;
// ...
这很可能还需要确保在Dispose执行时将一些内容添加到列表中。(您可以将私有类变量设置为本地方法变量,然后将类变量设置为空)
这篇关于在等待挂起的操作取消时处置SemaphoreSlim是否安全?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:在等待挂起的操作取消时处置SemaphoreSlim是否安全?


- 在哪里可以找到使用中的C#/XML文档注释的好例子? 2022-01-01
- 带有服务/守护程序应用程序的 Microsoft Graph CSharp SDK 和 OneDrive for Business - 配额方面返回 null 2022-01-01
- C# 中多线程网络服务器的模式 2022-01-01
- Web Api 中的 Swagger .netcore 3.1,使用 swagger UI 设置日期时间格式 2022-01-01
- 如何用自己压缩一个 IEnumerable 2022-01-01
- 良好实践:如何重用 .csproj 和 .sln 文件来为 CI 创建 2022-01-01
- WebMatrix WebSecurity PasswordSalt 2022-01-01
- MoreLinq maxBy vs LINQ max + where 2022-01-01
- C#MongoDB使用Builders查找派生对象 2022-09-04
- 输入按键事件处理程序 2022-01-01