C# ASP.NET锁线程方法
我正在使用C#开发一个ASP.NET表单Web应用程序。我有一个为客户创建新订单的方法。它看起来像这样C# ASP.NET锁线程方法,c#,asp.net,multithreading,methods,locking,C#,Asp.net,Multithreading,Methods,Locking,我正在使用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
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;
}
这里的问题是,两个请求(线程)中的一个客户可能会导致该方法被调用两次,而另一个线程也在该方法中。这可能导致创建两个订单
如何正确锁定此方法,使每个客户一次只能由一个线程执行
我试过了
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上,我不知道为什么。是否有错误,或者是否应使用其他方法锁定
谢谢在释放互斥时,您应该始终尝试最后一次。此外,请确保密钥正确(用户名)
除非我遗漏了什么,你就不能用普通锁吗
private object _locker = new object();
private string CreateOrder(string userName)
{
lock(_locker)
{
// 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;
}
}
在您的代码中,您正在惰性地创建互斥体。这会导致比赛条件。
例如,当您从另一个线程调用WaitOne()时,互斥锁可能仅部分构造。
您也可能创建两个互斥实例。
等等 您可以通过急切地创建实例来避免这种情况——例如,在Michael的代码中。 (请确保将其初始化为非国有状态。)
互斥体是一种内核级的同步原语-它比监视器(这是
lock
使用的)更昂贵。对于互斥体中的initiallyOwned
,传递false
。如果您创建互斥锁并最初拥有它,您需要再次调用ReleaseMutex
。我一直避免锁定基于web的应用程序-让web服务器处理线程,而是构建重复检测
你认为锁定CreateOrder会得到什么?在我看来,您可能会避免同时创建两个订单,但最终还是会创建两个订单 这样做更容易:
在这样的地方定义一个类:
public class MyLocks {
public static object OrderLock;
static MyLocks() {
OrderLock = new object();
}
}
然后在使用锁时执行以下操作:
lock(MyLocks.OrderLock) {
// put your code here
}
那就不太复杂了。无论出于什么目的定义锁都很简单,因为它们只是内存中非常小的对象,在多个线程中都是活动的。谢谢,不添加try/finally确实是一个错误。但不幸的是,这并不是问题的解决办法。这也是我突然想到的,也许有人能告诉我们互斥和锁的区别?我猜锁实际上只是一个表面下的互斥体,你使用互斥体是为了获得更多的功能,但这只是一个猜测…嗨,也许我应该锁定。使用互斥锁背后的想法是,我只需要锁定每个用户名的方法。我想用一个命名的互斥来实现这一点,它是全局的——“一个同步原语,也可以用于进程间同步”。你可以在同一台电脑上的进程之间使用它-例如,确保一个应用程序只启动一次…你是对的,笨蛋,我没有想到这一点。这导致了我试图避免的相同问题(部分构建的订单)。。。谢谢大家的回答。
lock(MyLocks.OrderLock) {
// put your code here
}