[英]Mutex not actually being released?
I have a web api controller that I want to restrict it to run only once at a time. 我有一个Web API控制器,我想限制它一次只能运行一次。 If a new request comes I want it to be rejected and not queued.
如果有新请求,我希望它被拒绝而不是排队。 I've implemented this behaviour using a Mutex, like in the following code:
我已经使用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();
}
Now if I call the controller 3 times in success, I get the following logs, which is exactly what I expected: 现在,如果我成功调用控制器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
But if I call it once more after release and close has been called, I just get 但是,如果我在释放并关闭后再次调用它,我会得到
2018-10-26 11:46:35.133 d6e4dd2e-16f1-43aa-b34b-226187dd9185 - Mutex exists
Shouldn't TryOpenExisting
fail after mutex has been released? 互斥量释放后,
TryOpenExisting
是否应该失败? Am I doing something wrong? 难道我做错了什么?
Rather than use a Mutex
, you should consider Monitor.TryEnter instead. 不要使用
Mutex
,而应该考虑使用Monitor.TryEnter 。
It functions like lock
, but returns immediately (as you want) if the lock is already taken. 它的功能类似于
lock
,但是如果已经获取了lock
,则会立即(根据需要)返回。
To do this, you will need to declare a static
lock object: 为此,您需要声明一个
static
锁对象:
private static object lockObject;
Or, if you need multiple locks (eg per database) then you would store those locks in a: 或者,如果您需要多个锁(例如,每个数据库),则可以将这些锁存储在以下位置:
private static ConcurrentDictionary<string, object> lockObjects = new ConcurrentDictionary<string, object>();
getting the lock object using GetOrAdd . 使用GetOrAdd获取锁对象。
Also, this will not work if you are using a web farm / web garden / load balancer either (since the lock will be process specific). 另外,如果您使用的是Web Farm / Web Garden / Load Balancer,则此方法也不起作用(因为锁定将是特定于进程的)。 If this is an issue for you, I'd consider using a queue - whereby every web server adds entries to the queue and a single queue consumer pulls off the queue and de-dupes the requests.
如果这对您来说是个问题,我会考虑使用队列 -每个Web服务器都会向该队列中添加条目,而单个队列使用方会拉出该队列并对请求进行重复数据删除。
Do you really need logic around whether the Mutex exists or not? 您是否真的需要有关Mutex是否存在的逻辑?
Why not always use var mutex = new Mutex(true, mutexName);
为什么不总是使用
var mutex = new Mutex(true, mutexName);
? ? You don't HAVE to check whether it exists or not.
您无需检查它是否存在。 And that check of
Mutex.TryOpenExisting
isn't threadsafe either. 而且对
Mutex.TryOpenExisting
检查Mutex.TryOpenExisting
是线程安全的。
EDIT 编辑
One more question, do you need a Mutex here, will a LOCK not be sufficient? 还有一个问题,您在这里需要Mutex吗,LOCK不够吗? Are you planning on running multiple instances of this WebAPI on the same server?
您是否打算在同一服务器上运行此WebAPI的多个实例? If not, then a Lock should be sufficient.
如果没有,那么一个锁应该足够了。
Mutex
- Work across Processes Mutex
跨流程工作
Lock
- Work across Threads Lock
-跨线程工作
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.