3

この問題に対処する方法が正確にはわかりません。私はそのように宣言されているミューテックスを持っています:

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();部分で例外が発生していることがわかりました。それはどういう意味で、どのように修正するのですか?

4

2 に答える 2

1

クラスとその使用方法にいくつかの問題があります。

  1. 以前にロックした場合にのみミューテックスを解放する必要があります(これはエラーです)
  2. 開いたミューテックスを閉じて破棄する必要があります
  3. また、クラスを作成するときではなく、使用する直前に作成することをお勧めしますMyClass

したがって、最初にクラスを次のように変更することをお勧めします。

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();
        }
    }
}
于 2013-03-15T00:22:27.297 に答える
1

finallyブロックでは、tryブロックで実際に取得したかどうかに関係なく、ミューテックスを解放しています。

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

falseを返す場合gl.enterLockWithTimeout、例外をスローしますが、finallyブロックのロックを解除しようとします。

于 2013-03-14T23:33:13.327 に答える