プログラムを中心とした個人的なメモ用のブログです。 タイトルは迷走中。
内容の保証はできませんのであしからずご了承ください。

2019/03/14

[C#] 排他オブジェクトのロック取得を待機しない場合

event_note2019/03/14 2:21

C# で排他制御を行う場合、lock を使うことが多いと思いますが、ロックを取得できなかった場合に待機せず、即タイムアウトにしたい場合の方法です。

lock だとタイムアウトを設定できないので、Monitor.TryEnter を使います。

bool acquiredLock = false;

try
{
    Monitor.TryEnter(lockObject, 0, ref acquiredLock);
    if (acquiredLock)
    {
        // ロック取得に成功したときの処理
    }
    else
    {
        // ロック取得に失敗したときの処理
    }
}
finally
{
    if (acquiredLock) Monitor.Exit(lockObject);
}

一応動作確認

var lockTest = new LockTest();
Parallel.For(0, 99, i =>
{
    lockTest.Hoge(i);
});
Console.WriteLine("完了");
Console.ReadKey();
class LockTest
{
    object lockObject = new object();
    int count = 0;

    public void Hoge(int i)
    {
        bool acquiredLock = false;

        try
        {
            Monitor.TryEnter(lockObject, 0, ref acquiredLock);
            if (acquiredLock)
            {
                // ロック取得に成功したときの処理
                count++;
                Console.WriteLine($"i={i}, {count}");
                Thread.Sleep(100);
            }
            else
            {
                // Console.WriteLine($"ロック取得失敗");
            }
        }
        finally
        {
            if (acquiredLock) Monitor.Exit(lockObject);
        }
    }
}

実行結果

i=24, 1
i=64, 2
i=65, 3
i=66, 4
i=67, 5
i=68, 6
i=69, 7
i=70, 8
i=71, 9
完了

参考 URL