Mutex在ASP.NET C#代码中发布问题

时间:2013-03-14 23:29:33

标签: c# asp.net locking mutex

我不确定如何解决这个问题。我有一个声明为这样的互斥锁:

public class MyNamedLock
{
    private Mutex mtx;
    private string _strLkName;

    public MyNamedLock(string strLockName)
    {
        _strLkName = strLockName;
        //...

        mtx = new Mutex(false, _strLkName, out bCreatedNew, mSec);
    }

    public bool enterLockWithTimeout(int nmsWait = 30 * 1000)
    {
        _nmsWaitLock = nmsWait;

        //Wait
        return mtx.WaitOne(nmsWait);
    }

    public void leaveLock()
    {
        _nmsWaitLock = 0;

        //Release it
        mtx.ReleaseMutex();
    }
}

然后它在ASP.NET页面中使用:

public class MyClass
{
    private MyNamedLock gl;

    public MyClass()
    {
        gl = new MyNamedLock("lock name");

    }


    public void funct()
    {
        try
        {
            //Enter lock
            if (gl.enterLockWithTimeout())
            {
                //Do work
            }
            else
                throw new Exception("Failed to enter lock");
        }
        finally
        {
            //Leave lock
            gl.leaveLock();
        }
    }
}

此代码在我的开发环境中没有给我带来任何麻烦,但在生产中它有时会抛出此异常:

  

从非同步块调用对象同步方法   代码。

描述有点模糊,但只是做了跟踪,我发现在mtx.ReleaseMutex();部分引发了异常。它是什么意思以及如何解决它?

2 个答案:

答案 0 :(得分:1)

在你的finally块中,无论你是否真的在try块中获取了互斥锁,你都会释放互斥锁。

try
{
    //Enter lock
    if (gl.enterLockWithTimeout())
    {
        //Do work
    }
    else throw new Exception("Failed to enter lock");
}
finally
{
    //Leave lock
    gl.leaveLock();
}

如果gl.enterLockWithTimeout返回false,您将抛出异常,但然后尝试释放finally块中的锁。

答案 1 :(得分:1)

您的班级以及使用方式上存在一些问题。

  1. 只有先前已锁定(这是您的错误)
  2. ,才能释放互斥锁
  3. 您需要关闭并处置已打开的互斥锁
  4. 最好在您使用它之前创建它,而不是在创建类MyClass时创建它。
  5. 因此,我建议您首先将您的课程更改为:

    public class MyNamedLock
    {
        private Mutex mtx = null;
        private string _strLkName;
    
        // to know if finally we get lock
        bool cNeedToBeRelease = false;
    
        public MyNamedLock(string strLockName)
        {
            _strLkName = strLockName;
            //...
    
            mtx = new Mutex(false, _strLkName, out bCreatedNew, mSec);
        }
    
        public bool enterLockWithTimeout(int nmsWait = 30 * 1000)
        {
            _nmsWaitLock = nmsWait;
            bool cLock = false;
            try
            {
                cLock = mtx.WaitOne(nmsWait, false);
                cNeedToBeRelease = cLock;    
            }
            catch (AbandonedMutexException)
            {
                // http://stackoverflow.com/questions/654166/wanted-cross-process-synch-that-doesnt-suffer-from-abandonedmutexexception
                // http://msdn.microsoft.com/en-us/library/system.threading.abandonedmutexexception.aspx
                cNeedToBeRelease = true;
            }
            catch (Exception x)
            {
                // log the error
                Debug.Fail("Check the reason of fail:" + x.ToString());
            }            
    
            return cLock;        
        }
    
        public void leaveLock()
        {
            _nmsWaitLock = 0;
    
            if (mtx != null)
            {
                if (cNeedToBeRelease)
                {
                    try
                    {
                        mtx.ReleaseMutex();
                        cNeedToBeRelease = false;    
                    }
                    catch (Exception x)
                    {
                        Debug.Fail("Check the reason of fail:" + x.ToString());
                    }
                }
    
                mtx.Close();
                mtx.Dispose();
                mtx = null;
            }
        }
    }
    

    这是你必须调用该类的方式:

    public class MyClass
    {
        public MyClass()
        {
        }
    
    
        public void funct()
        {
            var gl = new MyNamedLock("lock name");
            try
            {
                //Enter lock
                if (gl.enterLockWithTimeout())
                {
                    //Do work
                }
                else
                    throw new Exception("Failed to enter lock");
            }
            finally
            {
                //Leave lock
                gl.leaveLock();
            }
        }
    }