ASP.NET锁定线程的方法
我正在使用 C# 开发 ASP.NET 表单 Web 应用程序。我有一种为客户创建新订单的方法。它看起来与此类似;
private string CreateOrder(string userName) {
// Fetch current order
Order order = FetchOrder(userName);
if (order.OrderId == 0) {
// Has no order yet, create a new one
order.OrderNumber = Utility.GenerateOrderNumber();
order.Save();
}
return order;
}
这里的问题是,两个请求(线程)中的 1 个客户可能会导致该方法被调用两次,而另一个线程也在该方法内。这可能会导致创建两个订单。
如何正确锁定此方法,以便每个客户一次只能由一个线程执行?
我试过;
Mutex mutex = null;
private string CreateOrder(string userName) {
if (mutex == null) {
mutex = new Mutex(true, userName);
}
mutex.WaitOne();
// Code from above
mutex.ReleaseMutex();
mutex = null;
return order;
}
这可行,但在某些情况下它会挂在 WaitOne 上,我不知道为什么。是否有错误,或者我应该使用其他方法来锁定?
谢谢
I'm developing an ASP.NET forms webapplication using C#. I have a method which creates a new Order for a customer. It looks similar to this;
private string CreateOrder(string userName) {
// Fetch current order
Order order = FetchOrder(userName);
if (order.OrderId == 0) {
// Has no order yet, create a new one
order.OrderNumber = Utility.GenerateOrderNumber();
order.Save();
}
return order;
}
The problem here is, it is possible that 1 customer in two requests (threads) could cause this method to be called twice while another thread is also inside this method. This can cause two orders to be created.
How can I properly lock this method, so it can only be executed by one thread at a time per customer?
I tried;
Mutex mutex = null;
private string CreateOrder(string userName) {
if (mutex == null) {
mutex = new Mutex(true, userName);
}
mutex.WaitOne();
// Code from above
mutex.ReleaseMutex();
mutex = null;
return order;
}
This works, but on some occasions it hangs on WaitOne and I don't know why. Is there an error, or should I use another method to lock?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
在
mutex
构造函数中为initiallyOwned
传递false
。如果您创建互斥锁并最初拥有它,则需要再次调用ReleaseMutex
。Pass
false
forinitiallyOwned
in themutex
ctor. If you create the mutex and initially own it, you need to callReleaseMutex
again.释放互斥体时,您应该始终尝试最后。另外,请确保密钥正确(用户名)
You should always try finally when releasing mutex. Also, make sure that the key is correct(userName)
在您的代码中,您正在惰性地创建互斥体。这会导致竞争条件。
例如,当您从另一个线程调用 WaitOne() 时,可能会发生互斥体仅部分构造的情况。
您也可能创建两个互斥体实例。
等等...
您可以通过急切地创建实例来避免这种情况 - 即如迈克尔的代码所示。
(确保将其初始化为非拥有状态。)
Mutex 是内核级同步原语 - 它比 Monitor 更昂贵(这就是
lock
使用的功能。)。In your code, you are creating the mutex lazily. This leads to race conditions.
E.g. it can happen that the mutex is only partially constructed when you call WaitOne() from another thread.
It can also happen that you create two mutex instances.
etc...
You can avoid this by creating the instance eagerly - i.e. as in Michael's code.
(Be sure to initialize it to a non-owned state.)
Mutex is a kernel-level synchronization primitive - it is more expensive than Monitor (that is what
lock
uses.).除非我漏掉了什么,否则你不能用普通的锁吗?
Unless I'm missing something, can't you just use a regular lock?
我一直避免锁定基于 Web 的应用程序 - 让 Web 服务器处理线程,而是构建重复检测。
您认为通过锁定 CreateOrder 会得到什么?在我看来,您可以避免同时创建两个订单,但最终仍然会创建两个订单。
I have always avoided locking in a web-based application - let the web server deal with the threads, and instead build in duplicate detection.
What do you think you're going to get by locking on the CreateOrder? It seems to me that you may avoid creating two order simultaneously, but you're still going to end up with two orders created.
这样做更容易:
在某个地方定义一个类,如下所示:
然后在使用锁时执行以下操作:
那么它不是很复杂。无论出于何种目的定义锁都是轻量级的,因为它们只是内存中非常小的对象,在多个线程中都处于活动状态。
Its easier to do this:
define a class somewhere like so:
then when using the lock do this:
Its not very complicated then. Its light weight to define locks for whatever purpose as they are just very tiny objects in memory that are alive across multiple threads.