ASP.NET lock thread method

家住魔仙堡 提交于 2019-12-07 13:15:45

问题


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


回答1:


Pass false for initiallyOwned in the mutex ctor. If you create the mutex and initially own it, you need to call ReleaseMutex again.




回答2:


You should always try finally when releasing mutex. Also, make sure that the key is correct(userName)

Mutex mutex = null;
private string CreateOrder(string userName) {
    mutex = mutex ?? new Mutex(true, userName);
    mutex.WaitOne();
    try{
    // Code from above
    }finally{
    mutex.ReleaseMutex();
    }
    mutex = null;
    return order;
}



回答3:


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.).




回答4:


Unless I'm missing something, can't you just use a regular lock?

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;
    }
}



回答5:


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.




回答6:


Its easier to do this:

define a class somewhere like so:

public class MyLocks {
    public static object OrderLock;
    static MyLocks() {
        OrderLock = new object();
    }
}

then when using the lock do this:

lock(MyLocks.OrderLock) {
    // put your code here
}

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.



来源:https://stackoverflow.com/questions/2544452/asp-net-lock-thread-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!