SLa*_*aks 6 .net c# thread-safety
我有一个类允许其他线程等到它使用a完成一个操作ManualResetEventSlim.(操作通常很简短)
这个类没有明确的生命周期,因此没有一个地方可以轻松关闭事件.
相反,我希望在事件结束后立即关闭事件 - 一旦发出信号,并且在任何等待的线程唤醒之后.
出于性能原因,我宁愿不使用锁.
这段代码是否是线程安全的,是否可以更快?
volatile bool isCompleted;
volatile int waitingCount;
ManualResetEventSlim waiter = new ManualResetEventSlim();
//This method is called on any thread other than the one that calls OnCompleted
public void WaitForCompletion() {
if (isCompleted)
return;
Interlocked.Increment(ref waitingCount);
Thread.MemoryBarrier();
if (!isCompleted)
waiter.Wait();
if (0 == Interlocked.Decrement(ref waitingCount)) {
waiter.Dispose();
waiter = null;
}
return;
}
//This method is called exactly once.
protected internal virtual void OnCompleted(string result) {
Result = result;
isCompleted = true;
Thread.MemoryBarrier();
if (waitingCount == 0) {
waiter.Dispose();
waiter = null;
} else
waiter.Set();
}
Run Code Online (Sandbox Code Playgroud)
我在您的代码中看到的最重要的事情是调用后waiterto的设置。我在我负责的非托管接口上有大量托管包装器,当我迁移到 .Net 4.0 时,这种做法在某些线程场景中又给我带来了困扰。nullDispose
MSDN 上的信息ManualResetEventSlim.Dispose表明它不是线程安全的,但是,查看其实际实现,Dispose从多个线程进行多次调用并没有什么危险。此外, 的实现IDisposable应该能够非常容忍多次调用(如其设计指南中所指定)。
我曾经考虑过的一个想法是OnCompleted稍微重新排序,以允许读者在完成后不久订阅:
//This method is called exactly once.
protected internal virtual void OnCompleted(string result) {
Result = result;
isCompleted = true;
waiter.Set();
Thread.MemoryBarrier();
if (waitingCount == 0) {
waiter.Dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1329 次 |
| 最近记录: |