[英]Mutex not actually being released?
我有一个Web API控制器,我想限制它一次只能运行一次。 如果有新请求,我希望它被拒绝而不是排队。 我已经使用Mutex实现了此行为,如以下代码所示:
public IHttpActionResult Get()
{
string token = Utils.GetCurrentToken(RequestContext);
//Some irrelevant code
Task.Factory.StartNew(() =>
{
var mutexName = Utils.GetDBFromToken(token).ProjectID.ToString();
var success = Mutex.TryOpenExisting(mutexName, out Mutex mutex);
if (!success || mutex == null)
{
mutex = new Mutex(true, mutexName);
Utils.Log(token, mutexName + " - Mutex created");
}
else
{
Utils.Log(token, mutexName + " - Mutex exists");
return;
}
try
{
mutex.WaitOne();
try
{
Utils.Log(token, mutexName + " - Job started");
Thread.Sleep(10000);
Utils.Log(token, mutexName + " - Job ended");
}
catch (Exception ex)
{
//Handle error
}
}
finally
{
Utils.Log(token, mutexName + " - About to release mutex");
if (mutex != null)
{
mutex.ReleaseMutex();
mutex.Close();
mutex.Dispose();
Utils.Log(token, mutexName + " - Mutex released");
}
}
});
return Ok();
}
现在,如果我成功调用控制器3次,则会得到以下日志,这正是我的预期:
2018-10-26 11:45:11.650 d6e4dd2e-16f1-43aa-b34b-226187dd9185 - Mutex created
2018-10-26 11:45:11.870 d6e4dd2e-16f1-43aa-b34b-226187dd9185 - Mutex exists
2018-10-26 11:45:11.963 d6e4dd2e-16f1-43aa-b34b-226187dd9185 - Mutex exists
2018-10-26 11:45:12.323 d6e4dd2e-16f1-43aa-b34b-226187dd9185 - Job started
2018-10-26 11:45:22.633 d6e4dd2e-16f1-43aa-b34b-226187dd9185 - Job ended
2018-10-26 11:45:22.947 d6e4dd2e-16f1-43aa-b34b-226187dd9185 - About to release mutex
2018-10-26 11:45:23.290 d6e4dd2e-16f1-43aa-b34b-226187dd9185 - Mutex released
但是,如果我在释放并关闭后再次调用它,我会得到
2018-10-26 11:46:35.133 d6e4dd2e-16f1-43aa-b34b-226187dd9185 - Mutex exists
互斥量释放后, TryOpenExisting
是否应该失败? 难道我做错了什么?
不要使用Mutex
,而应该考虑使用Monitor.TryEnter 。
它的功能类似于lock
,但是如果已经获取了lock
,则会立即(根据需要)返回。
为此,您需要声明一个static
锁对象:
private static object lockObject;
或者,如果您需要多个锁(例如,每个数据库),则可以将这些锁存储在以下位置:
private static ConcurrentDictionary<string, object> lockObjects = new ConcurrentDictionary<string, object>();
使用GetOrAdd获取锁对象。
另外,如果您使用的是Web Farm / Web Garden / Load Balancer,则此方法也不起作用(因为锁定将是特定于进程的)。 如果这对您来说是个问题,我会考虑使用队列 -每个Web服务器都会向该队列中添加条目,而单个队列使用方会拉出该队列并对请求进行重复数据删除。
您是否真的需要有关Mutex是否存在的逻辑?
为什么不总是使用var mutex = new Mutex(true, mutexName);
? 您无需检查它是否存在。 而且对Mutex.TryOpenExisting
检查Mutex.TryOpenExisting
是线程安全的。
编辑
还有一个问题,您在这里需要Mutex吗,LOCK不够吗? 您是否打算在同一服务器上运行此WebAPI的多个实例? 如果没有,那么一个锁应该足够了。
Mutex
跨流程工作
Lock
-跨线程工作
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.