C# ASP.NET锁线程方法

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

我正在使用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;
    }
这里的问题是,两个请求(线程)中的一个客户可能会导致该方法被调用两次,而另一个线程也在该方法中。这可能导致创建两个订单

如何正确锁定此方法,使每个客户一次只能由一个线程执行

我试过了

    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
}