我想使用鎖定或類似的同步來保護關鍵部分。同時我想收聽CancellationToken。c#鎖定並收聽CancellationToken
現在我正在使用這樣的互斥量,但互斥量沒有那麼好的性能。我可以使用任何其他同步類(包括新的.Net 4.0)而不是互斥量嗎?
WaitHandle.WaitAny(new[] { CancelToken.WaitHandle, _mutex});
CancelToken.ThrowIfCancellationRequested();
我想使用鎖定或類似的同步來保護關鍵部分。同時我想收聽CancellationToken。c#鎖定並收聽CancellationToken
現在我正在使用這樣的互斥量,但互斥量沒有那麼好的性能。我可以使用任何其他同步類(包括新的.Net 4.0)而不是互斥量嗎?
WaitHandle.WaitAny(new[] { CancelToken.WaitHandle, _mutex});
CancelToken.ThrowIfCancellationRequested();
在.NET 4.0 Framework
新功能SemaphoreSlim Class看看。它提供了SemaphoreSlim.Wait(CancellationToken)方法。
阻止當前線程,直到它可以進入SemaphoreSlim,而 觀察的CancellationToken
從在這種簡單的情況下,使用旗語某些角度來看,因爲它最初的目的是提供可能是一個開銷一個多線程訪問,但也許你可能會覺得它很有用。
編輯:代碼片段
CancellationToken token = new CancellationToken();
SemaphoreSlim semaphore = new SemaphoreSlim(1,1);
try {
// block section entrance for other threads
semaphore.Wait(token);
// critical section code
// ...
if (token.IsCancellationRequested)
{
// ...
}
}
finally {
semaphore.Release();
}
可以使用Monitor
對象來獲得性能上的位因爲它也表示在MSDN:
雖然互斥可用於幀內處理線程同步,使用監視器通常是優選的,因爲顯示器是爲.NET Framework專門設計的,因此更好地利用資源
的更多信息
http://msdn.microsoft.com/en-us/library/system.threading.monitor.aspx
CancellationToken
爲您提供了異步或長時間運行的同步操作的協作取消模型。 如果您想要將它與監視器類一起使用,則必須構造代碼才能釋放鎖,前提是這是取消請求。你可以這樣做以下:
public void ThreadSafeMethod()
{
var cancellationToken=new CancellationToken();
object locker=new object();
Monitor.Enter(locker);
try
{
//your code
if (token.IsCancellationRequested)
{
Monitor.Exit(locker);
}
}
finally
{
Monitor.Exit(locker);
}
}
,或者如果你想使用ThrowIfCancellationRequested:
public void ThreadSafeMethod()
{
var cancellationToken=new CancellationToken();
object locker=new object();
Monitor.Enter(locker);
try
{
//your code
cancellationToken.ThrowIfCancellationRequested();
}
catch(OperationCanceledException)
{
}
finally
{
Monitor.Exit(locker);
}
}
private object _lockObject = new object();
lock (_lockObject)
{
// critical section
using (token.Register(() => token.ThrowIfCancellationRequested())
{
// Do something that might need cancelling.
}
}
令牌上調用Cancel()
將導致ThrowIfCancellationRequested()
因爲這是什麼掛接到Register
回調被調用。你可以在這裏放置任何你想要的取消邏輯。這種方法非常棒,因爲您可以通過強制導致呼叫完成的條件來取消阻塞呼叫。
ThrowIfCancellationRequested拋出OperationCanceledException。您需要在調用線程上處理此問題,否則您的整個過程可能會被取消。這樣做的一個簡單方法是使用Task類開始您的任務,該類將聚合所有例外,供您在調用線程上處理。
try
{
var t = new Task(() => LongRunningMethod());
t.Start();
t.Wait();
}
catch (AggregateException ex)
{
ex.Handle(x => true); // this effectively swallows any exceptions
}
一些好東西here覆蓋合作社消除
在調用線程時拋出異常Cancel – Karsten
如果您的意思是OperationCanceledException,那麼這是由設計決定的 - 這就是ThrowIfCancellationRequested方法拋出的。您應該使用建議的模式(更新的答案)在呼叫方處理它。 –
關於你的語句「調用'Cancel()'在CancellationTokenSource上將導致'ThrowIfCancellationRequested()'被調用」...這個行爲可以通過使用[Cancel(bool)](https:// msdn .microsoft.com/en-us/library/dd321703(v = vs.110).aspx)過載。 –
你可以張貼一些代碼顯示了關鍵部分,你目前如何釋放互斥? –