急切地处置一个ManualResetEvent的 [英] Eagerly Disposing a ManualResetEvent

查看:123
本文介绍了急切地处置一个ManualResetEvent的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类,允许其他线程等待,直到它使用 ManualResetEventSlim 完成的操作。 (该操作通常是短暂的)

本类没有明确的寿命,所以我可以很容易地关闭事件没有任何一个地方。
相反,我想,因为它是完成与mdash一旦关闭事件,只要它发出信号,之后等待的线程醒来

有关性能方面的原因,我想preFER不使用锁。

这是code线程安全的,可以将其进行得更快?

 挥发性布尔isCompleted;
挥发性INT waitingCount;
ManualResetEventSlim服务员=新ManualResetEventSlim();

//调用此方法比上一个调用其他任何线程OnCompleted
公共无效WaitForCompletion(){
    如果(isCompleted)
        返回;

    Interlocked.Increment(REF waitingCount);
    Thread.MemoryBarrier();
    如果(!isCompleted)
        waiter.Wait();

    如果(0 == Interlocked.Decrement(REF waitingCount)){
        waiter.Dispose();
        服务员= NULL;
    }
    返回;
}

//这种方法被称为一次。
受保护的内部虚拟无效OnCompleted(字符串结果){
    结果=结果;
    isCompleted = TRUE;
    Thread.MemoryBarrier();
    如果(waitingCount == 0){
        waiter.Dispose();
        服务员= NULL;
    } 其他
        waiter.Set();
}
 

解决方案

我和你code看到的最重要的事情是服务员来设置调用处置之后。我有超过我负责的这一点,当我移动到.NET 4.0这种做法回来咬我在某些线程情况下非托管接口托管包装的庞大的身躯。

ManualResetEventSlim.Dispose MSDN的资料表明,它不是线程安全的,但是,看在它的实际执行没有什么危险的约处置从多个线程。此外,的IDisposable 的实施被认为是的非常的多次调用(如在他们的设计指导规定)。宽容

<打击>一个想法我会玩弄会重新排列 OnCompleted 稍微让读者是否赞同不久它完成后:

  //此方法被调用一次。
受保护的内部虚拟无效OnCompleted(字符串结果){
    结果=结果;
    isCompleted = TRUE;

    waiter.Set();
    Thread.MemoryBarrier();
    如果(waitingCount == 0){
        waiter.Dispose();
    }
}
 

I have a class which allows other threads to wait until it finishes an operation using a ManualResetEventSlim. (The operations are typically brief)

This class has no explicit lifetime, so there is no single place that I can easily close the event.
Instead, I want to close the event as soon as it's finished with—as soon as it's signalled, and after any waiting threads wake up.

For performance reasons, I'd prefer not to use a lock.

Is this code thread-safe, and can it be made faster?

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();
}

解决方案

The biggest thing I see with your code is the setting of the waiter to null after calling Dispose. I have a large body of managed wrappers over unmanaged interfaces that I am in charge of and when I moved to .Net 4.0 this practice came back to bite me in some threading scenarios.

The MSDN information on ManualResetEventSlim.Dispose suggests that it is not threadsafe, however, looking over its actual implementation there is nothing dangerous about multiple invocations of Dispose from multiple threads. Additionally, implementations of IDisposable are supposed to be very tolerant of multiple invocations (as specified in their design guidance).

One idea I'd toyed with would reorder OnCompleted slightly to allow a reader if it subscribes shortly after it completes:

//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();
    }
}

这篇关于急切地处置一个ManualResetEvent的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆