gpt4 book ai didi

c# - 在异步方法中根据 Id 锁定

转载 作者:太空宇宙 更新时间:2023-11-03 15:03:00 24 4
gpt4 key购买 nike

我有一个 MVC 应用程序,其中必须按特定顺序执行操作方法。最近,我遇到了一些奇怪的问题,我假设是因为我没有进行任何线程同步。我几乎没有接触过多线程,对此我了解不多。我尝试实现某种锁定,我必须根据 Id 进行锁定。所以我实现了如下类来获取所需的锁对象。

public class ReportLockProvider
: IReportLockProvider
{
readonly ConcurrentDictionary<long, object> lockDictionary
= new ConcurrentDictionary<long, object>();

public object ProvideLockObject(long reportId)
{
return lockDictionary.GetOrAdd(reportId, new object());
}
}

我尝试如下使用它:

ReportLockProvider lockProvider = new ReportLockProvider();

public async ActionResult MyAction(long reportId)
{
lock(lockProvider.ProvideLockObject(reportId))
{
// Some operations
await Something();
// Some operation
}
}

我希望它能工作,但它没有编译,因为我在 lock 主体中使用了 await 。我搜索了一下,在 this answer 中找到了 SemaphoreSlim .现在,问题是我必须根据 Id 获取锁定对象。我怎样才能做到这一点?可以创建多个 SemaphoreSlim 对象吗? 如果我修改如下代码是否可以:

public class ReportLockProvider
: IReportLockProvider
{
readonly ConcurrentDictionary<long, SemaphoreSlim> lockDictionary
= new ConcurrentDictionary<long, SemaphoreSlim>();

public SemaphoreSlim ProvideLockObject(long reportId)
{
return lockDictionary.GetOrAdd(reportId, new SemaphoreSlim(1, 1));
}
}


public async ActionResult MyAction(long reportId)
{
var lockObject = ReportLockProvider.ProvideLockObject(reportId);

await lockObject.WaitAsync();
try
{
// Some operations
await Something();
// Some operation
}
finally
{
lockObject.Release();
}
}

另一个问题是,我可以在非异步 方法中使用SemaphoreSlim 吗? 还有更好的选择吗?

最佳答案

我认为您在 lockDictionary 前面缺少一个静态关键字,但这取决于您如何实例化提供者。

这是一个示例,其中包含我在 LinqPad 中编写的一些更改代码:

async Task Main()
{
ReportLockProvider reportLockProvider = new ReportLockProvider();
List<Task> tasks = new List<Task>(10);

for (long i = 1; i <= 5; i++) {
var local = i;
tasks.Add(Task.Run(() => Enter(local) ));
tasks.Add(Task.Run(() => Enter(local) ));
}

async Task Enter(long id)
{
Console.WriteLine(id + " waiting to enter");
await reportLockProvider.WaitAsync(id);

Console.WriteLine(id + " entered!");
Thread.Sleep(1000 * (int)id);

Console.WriteLine(id + " releasing");
reportLockProvider.Release(id);
}

await Task.WhenAll(tasks.ToArray());
}

public class ReportLockProvider
{
static readonly ConcurrentDictionary<long, SemaphoreSlim> lockDictionary = new ConcurrentDictionary<long, SemaphoreSlim>();

public async Task WaitAsync(long reportId)
{
await lockDictionary.GetOrAdd(reportId, new SemaphoreSlim(1, 1)).WaitAsync();
}
public void Release(long reportId)
{
SemaphoreSlim semaphore;
if (lockDictionary.TryGetValue(reportId, out semaphore))
{
semaphore.Release();
}
}
}

关于c# - 在异步方法中根据 Id 锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45214268/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com