Gibt es in C# den Vorgang „Sperren versuchen, bei Zeitüberschreitung überspringen“?
-
08-06-2019 - |
Frage
Ich muss versuchen, ein Objekt zu sperren, und wenn es bereits gesperrt ist, fahre einfach fort (nach einer Zeitüberschreitung oder ohne Zeitüberschreitung).
Die C#-Sperranweisung blockiert.
Lösung
Ich glaube, dass Sie verwenden können Monitor.TryEnter()
.
Die Lock-Anweisung wird einfach in a übersetzt Monitor.Enter()
Anruf und a try catch
Block.
Andere Tipps
Ed hat die richtige Funktion für Sie.Vergessen Sie nicht, anzurufen Monitor.Exit()
.Sie sollten a verwenden try-finally
blockieren, um eine ordnungsgemäße Reinigung zu gewährleisten.
if (Monitor.TryEnter(someObject))
{
try
{
// use object
}
finally
{
Monitor.Exit(someObject);
}
}
Ich hatte das gleiche Problem, am Ende habe ich eine Klasse erstellt TryLock
das implementiert IDisposable und verwendet dann das using
Anweisung zur Steuerung des Sperrbereichs:
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;
}
}
}
Und verwenden Sie dann die folgende Syntax zum Sperren:
var obj = new object();
using (var tryLock = new TryLock(obj))
{
if (tryLock.HasLock)
{
Console.WriteLine("Lock acquired..");
}
}
Sie werden das jetzt wahrscheinlich selbst herausfinden, nachdem die anderen Sie in die richtige Richtung gewiesen haben, aber TryEnter kann auch einen Timeout-Parameter annehmen.
Jeff Richters „CLR Via C#“ ist ein ausgezeichnetes Buch über Details der CLR-Innereien, wenn Sie sich mit komplizierteren Dingen befassen.
Erwägen Sie die Verwendung von AutoResetEvent und seiner Methode WaitOne mit einer Timeout-Eingabe.
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.");
}
Sehen 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 Und https://msdn.microsoft.com/en-us/library/cc190477(v=vs.110).aspx