C# に「ロックを試行し、タイムアウトになったらスキップする」操作はありますか?
-
08-06-2019 - |
質問
オブジェクトをロックオンする必要があります。すでにロックされている場合は、(タイムアウト後、またはロックなしで) 続行します。
C# の lock ステートメントがブロックされています。
解決
使っていただけると思います Monitor.TryEnter()
.
lock ステートメントは単に次のように変換されます。 Monitor.Enter()
電話と try catch
ブロック。
他のヒント
エドはあなたにぴったりの機能を提供します。ただ電話するのを忘れないでください Monitor.Exit()
. 。を使用する必要があります try-finally
ブロックして、適切なクリーンアップを保証します。
if (Monitor.TryEnter(someObject))
{
try
{
// use object
}
finally
{
Monitor.Exit(someObject);
}
}
私も同じ問題を抱えていたので、結局クラスを作成しました TryLock
IDisposable を実装し、 using
ロックの範囲を制御するステートメント:
public class TryLock : IDisposable
{
private object locked;
public bool HasLock { get; private set; }
public TryLock(object obj)
{
if (Monitor.TryEnter(obj))
{
HasLock = true;
locked = obj;
}
}
public void Dispose()
{
if (HasLock)
{
Monitor.Exit(locked);
locked = null;
HasLock = false;
}
}
}
次に、次の構文を使用してロックします。
var obj = new object();
using (var tryLock = new TryLock(obj))
{
if (tryLock.HasLock)
{
Console.WriteLine("Lock acquired..");
}
}
他の人が正しい方向を示してくれたので、おそらく自分でこれを見つけるでしょうが、TryEnter はタイムアウト パラメーターを取ることもできます。
Jeff Richter の『CLR Via C#』は、より複雑な内容に興味がある場合、CLR の内部の詳細について説明した優れた本です。
AutoResetEvent とそのメソッド WaitOne をタイムアウト入力とともに使用することを検討してください。
static AutoResetEvent autoEvent = new AutoResetEvent(true);
if(autoEvent.WaitOne(0))
{
//start critical section
Console.WriteLine("no other thread here, do your job");
Thread.Sleep(5000);
//end critical section
autoEvent.Set();
}
else
{
Console.WriteLine("A thread working already at this time.");
}
見る https://msdn.microsoft.com/en-us/library/cc189907(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/system.threading.autoresetevent(v=vs.110).aspx そして https://msdn.microsoft.com/en-us/library/cc190477(v=vs.110).aspx