1

小さなコードを書きました。以下のようなもの

    public static void SetLicence1()
    {
            Console.WriteLine("Setting Aspose Licence in Thread1 ");
            Console.WriteLine(SetAsposeLicense());
    }

    public static void SetLicence2()
    {
        Console.WriteLine("Setting Aspose Licence in Thread2 ");
        Console.WriteLine(SetAsposeLicense());
    }

    public static bool SetAsposeLicense()
    {
        try
        {
            //Declare Mutex variable:            
            using (Mutex mutex = new System.Threading.Mutex(false, "Test"))
            {
                    mutex.WaitOne(TimeSpan.FromSeconds(5));
                    var objLic = new License();
                    objLic.SetLicense(@"C:\Nivedita\License\Aspose.Cells.lic");
                    mutex.ReleaseMutex();
            }
            return true;
        }
        catch(Exception ex)
        {
               Console.WriteLine(ex.StackTrace);               
               return false;
        }
    }       
}

public class TestClass
{
    public static void Main()
    {
        Thread tid1 = new Thread(new ThreadStart(ThreadClass.SetLicence1));
        Thread tid2 = new Thread(new ThreadStart(ThreadClass.SetLicence2));

        tid1.Start();
        tid2.Start();

        Console.Read();
    }
}

このコードは完全に正常に機能しています。しかし、ここで私の質問は、WaitOne() メソッドがプロセス内またはプロセス間でスタックし、ミューテックス オブジェクトが解放されない可能性はありますか? 私はmutex.ReleaseMutex()を使用しましたが。

4

3 に答える 3

2

まず第一に、あなたの意図が何であるかははっきりしていません。ライセンスを2つのスレッドで同時に設定できないようにするだけの場合は、次のようなものが必要です。

static object s_lock = new object();

public static bool SetAsposeLicense()
{
    try
    {
        lock (s_lock)
        {
            var objLic = new License();
            objLic.SetLicense(@"C:\Nivedita\License\Aspose.Cells.lic");

        }
        return true;
    }
    catch(Exception ex)
    {
           Console.WriteLine(ex.StackTrace);               
           return false;
    }
}       

ここでは5秒のタイムアウトがないことに気づきました。5秒間待って、他のスレッドが終了したかどうかに関係なくライセンスを設定したい場合(基本的には質問のコードが何をするか)、mutexをいじる代わりに、これを行う方が良いです(しかし、私は理解するのに苦労しています、なぜこれが欲しいですか):

private static object s_lock = new object();

public static bool SetAsposeLicense()
{
    if (Monitor.TryEnter(s_lock, TimeSpan.FromSeconds(5)))
    {
        try 
        {
            return SetLicenseInternal(); 
        }
        finally 
        {
            Monitor.Exit(s_lock);
        }
    }
    return SetLicenseInternal(); 
}

public static bool SetLicenseInternal()
{
    try
    {
        var objLic = new License();
        objLic.SetLicense(@"C:\Nivedita\License\Aspose.Cells.lic");
        return true;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.StackTrace);
        return false;
    }
}

Monitorオブジェクトを使用することは、ミューテックスを使用するよりも「ネイティブ」なアプローチであり、クロスプロセスを必要としないため、ここにより適しています。

Mutexに関する限り、これは.NETに表示されるシステムMutexオブジェクトに対するラッパーです。名前付きミューテックスはシステム全体であり、プロセス全体で表示されます。.NET Mutexオブジェクトを作成して名前を指定すると、この名前のシステムMutexが存在しない場合は、作成されて、取得した.NETオブジェクトにラップされます。この名前のシステムMutexが以前に作成されている場合、この既存のMutexはラップされ、新しい.NETMutexオブジェクトとして返されます。

シナリオでミューテックスを使用するべきではないと思います。

于 2013-02-15T01:01:56.667 に答える
1

WaitOneは、それを保持していたプロセスが解放せずに終了した場合、AbandondMutexExceptionをスローします。try / finalブロックを使用しても、Visual Studioの間違った場所でデバッグを停止したり、タスクマネージャーを使用してプロセスを終了したりすると、これが発生する可能性があります。この場合は、ミューテックスを再ロックするか、アプリケーションを終了する必要があります。スローされた例外が原因でロックが取得されなかった場合も、releaseの呼び出しがスローされることに注意してください。

于 2013-02-15T01:08:20.740 に答える
-1

編集:この答えが間違っていることを知りました。 zespriは以​​下で説明します。


ブロックが終了するmutexとすぐに破棄されるため、解放されない可能性はありません。メソッドにスコープが設定されているため、using他には何も表示されません。mutexここには、 2 つの独立したMutexオブジェクトがあり、1 つは Thread1 に、もう 1 つは Thread2 にあることに注意してください。これは単に の間違った使い方ですMutex

が必要な場合はMutex、代わりにこれを試してください。

private static Mutex mutex = new Mutex(false, "Test");

public static bool SetAsposeLicense()
{
    try
    {
        if (!mutex.WaitOne(TimeSpan.FromSeconds(5))
        {
            throw new TimeoutException("Aspose license registration timed out.");
        }
        try
        {
            var objLic = new License();
            objLic.SetLicense(@"C:\Nivedita\License\Aspose.Cells.lic");
            return true;
        }
        finally
        {
            mutex.ReleaseMutex();
        }
    }
    catch(Exception ex)
    {
        Console.WriteLine(ex.StackTrace);
        return false;
    }
}

変更点:

  • すべてmutexのスレッドが同じ を参照できるように、クラス メンバーを作成しますMutex

  • mutex解放されたかどうか、またはタイムアウトしたかどうかを確認します。

  • ネストされたtry/finallyブロックを追加してmutex、ライセンスを設定すると例外がスローされた場合に解放されるようにします。ReleaseMetux()を正常に呼び出したスレッドによってのみ呼び出すことができるため、ネストが必要ですWaitOne()

于 2013-02-14T22:32:32.757 に答える