【发布时间】:2021-06-26 20:33:52
【问题描述】:
我刚刚开始使用Nito.AsyncEx 包和AsyncLock 而不是普通的lock() { ... } 部分,我在锁定部分中有async 调用(因为在这种情况下你不能使用lock() good reasons 我刚刚读到)。这是我从 Hangfire 运行的一项工作。我们称其为“工作线程”。
在另一个线程中,来自 ASP.NET 控制器,我想检查是否有一个线程当前正在锁定部分内执行。如果锁定部分中没有线程,那么我将通过 Hangfire 安排后台作业。如果锁定部分中已经有一个线程,那么我不想安排另一个线程。 (是的,这听起来可能有点奇怪,但那是另一回事了)。
有没有办法使用Nito.AsyncEx 对象来检查这一点,还是我应该在锁定部分的开头设置一个标志并在最后取消设置?
例如我想要这个:
public async Task DoAJobInTheBackground(string queueName, int someParam)
{
// do other stuff...
// Ensure I'm the only job in this section
using (await _asyncLock.LockAsync())
{
await _aService.CallSomethingAsync());
}
// do other stuff...
}
并从控制器调用的服务中使用我想象的方法IsSomeoneInThereNow():
public void ScheduleAJobUnlessOneIsRunning(string queueName, int someParam)
{
if (!_asyncLock.IsSomeoneInThereNow())
{
_backgroundJobClient.Enqueue<MyJob>(x =>
x.DoAJobInTheBackground(queueName, someParam));
}
}
但到目前为止,我只能看到如何使用单独的变量来执行此操作(想象 _isAnybodyInHere 是 thread-safe bool 或者我改用了 Interlocked):
public async Task DoAJobInTheBackground(string queueName, int someParam)
{
// do other stuff...
// Ensure I'm the only job in this section
using (await _asyncLock.LockAsync())
{
try
{
_isAnybodyInHere = true;
await _aService.CallSomethingAsync());
}
finally
{
_isAnybodyInHere = false;
}
}
// do other stuff...
}
以及来自控制器调用的服务:
public void ScheduleAJobUnlessOneIsRunning(string queueName, int someParam)
{
if (!_isAnybodyInHere)
{
_backgroundJobClient.Enqueue<MyJob>(x =>
x.DoAJobInTheBackground(queueName, someParam));
}
}
真的感觉应该有更好的方法。 AsyncLockdoc says:
您可以使用 already-cancelled CancellationToken 调用 Lock 或 LockAsync 尝试立即获取 AsyncLock 没有实际进入等待队列。
但我不明白该怎么做,至少使用同步 Lock 方法。
【问题讨论】:
标签: c# multithreading asp.net-core asynchronous nito.asyncex