c# - 在方法中使用SemaphoreSlim而不进行异常处理

标签 c# multithreading locking async-await semaphore

目前我正在努力实现 SemaphoreSlim用于“锁定”必须是线程安全的方法的“部分”。我的问题是,在没有重载异常处理的情况下实现这一点非常困难。因为当在释放“锁”之前抛出异常时,它会永远留在那里。

这是一个例子:

private SemaphoreSlim _syncLock = new SemaphoreSlim(1);
private IDictionary<string, string> dict = new Dictionary<string, string>();

public async Task ProcessSomeThing(string input)
{
    string someValue = await GetSomeValueFromAsyncMethod(input);
    await _syncLock.WaitAsync();
    dict.Add(input, someValue);
    _syncLock.Release();
}

如果输入多次具有相同的值,此方法将引发异常,因为具有相同键的项目将被添加到字典中两次,并且“锁”不会被释放。

假设我有很多 _syncLock.Release();_syncLock.Release(); ,很难写出try-catch.ContainsKey或者是其他东西。这会完全破坏代码......是否可以在 Exception 时始终释放锁?被抛出或某些术语被留下?

希望我的要求/渴望是什么很清楚。

谢谢大家!

最佳答案

我建议不要使用lockSemaphoreSlim 。相反,使用正确的工具来完成工作 - 在这种情况下,使用 ConcurrentDictionary<TKey, Lazy<TValue>> 似乎是合适的。过度使用 IDictionary<string, string>以及锁定和信号量。一年前已经有几篇关于这种模式的文章,here's one of the them 。因此,遵循这个建议的模式将如下所示:

private ConcurrentDictionary<string, Lazy<Task<string>>> dict = 
    new ConcurrentDictionary<string, Lazy<Task<string>>>();

public Task ProcessSomeThing(string input)
{
    return dict.AddOrUpdate(
        input, 
        key => new Lazy<Task<string>>(() => 
            GetSomeValueFromAsyncMethod(key), 
            LazyThreadSafetyMode.ExecutionAndPublication),
        (key, existingValue) => new Lazy<Task<string>>(() => 
            GetSomeValueFromAsyncMethod(key), // unless you want the old value
            LazyThreadSafetyMode.ExecutionAndPublication)).Value;
}

最终这实现了 asynchronously线程安全目标添加到您的dictionary 。错误处理按照您的预期发生,假设有 try / catch在你的GetSomeValueFromAsyncMethod功能。更多资源:

最后,我创建了an example .NET fiddle to help demonstrate the idea .

关于c# - 在方法中使用SemaphoreSlim而不进行异常处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35752306/

相关文章:

c# - Windows 服务可以在未登录的情况下启动应用程序吗?

python - pyaudio - "Listen"直到检测到语音然后录制到 .wav 文件

postgresql - PostgreSQL 表上的 SELECT COUNT(*) 是否会锁定它?

python - bash 使用套接字的锁定机制

c# - 防止多次调用事件方法(锁定)

c# - 使用 MONO 降级 Web API 以在 Linux 上运行

c# - 如何确定哪个属性是数据绑定(bind)的默认属性?

c# - 组合键作为外键

mysql - 多线程访问MySQL错误

python - 在 Python 中序列化 Sqlite3