.NET反转信号量? [英] .NET Reverse Semaphore?

查看:134
本文介绍了.NET反转信号量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

也许为时已晚,在晚上,但我想不出一个很好的办法做到这一点。

我已经开始了一堆异步下载,我想等到他们都完成之前,该程序将终止。这使我相信我应该增加一些下载启动时,和减少它,当它完成。但后来的我怎么等到计数为0 一次?

信号灯排序在相反的方向,你阻止的工作时,有没有资源可用,而不是在他们的所有可用(块时数为0,而不是非零值)。


根据这里的建议,这是我想出了。除了等待,直到计数为0,则如果产卵过多线程(计数>最大)睡觉。 警告:这是不完全测试

 公共类ThreadCounter
{
    #区域变量
    私人诠释CURRENTCOUNT,MAXCOUNT;
    私人ManualResetEvent的eqZeroEvent;
    私有对象instanceLock =新的对象();
    #endregion

    #区域属性
    公众诠释CURRENTCOUNT
    {
        得到
        {
            返回CURRENTCOUNT;
        }
        组
        {
            锁定(instanceLock)
            {
                CURRENTCOUNT =价值;
                AdjustZeroEvent();
                AdjustMaxEvent();
            }
        }
    }

    公众诠释MAXCOUNT
    {
        得到
        {
            返回MAXCOUNT;
        }
        组
        {
            锁定(instanceLock)
            {
                MAXCOUNT =价值;
                AdjustMaxEvent();
            }
        }
    }
    #endregion

    #区域构造
    公共ThreadCounter():这个(0){}
    公共ThreadCounter(INT initialCount):这个(initialCount,int.MaxValue){}
    公共ThreadCounter(INT initialCount,INT maximumCount)
    {
        CURRENTCOUNT = initialCount;
        MAXCOUNT = maximumCount;
        eqZeroEvent = CURRENTCOUNT == 0?新的ManualResetEvent(真):新的ManualResetEvent(假);
    }
    #endregion

    #地区的公共方法
    公共无效增量()
    {
        ++ CURRENTCOUNT;
    }

    公共无效递减()
    {
        --CurrentCount;
    }

    公共无效WaitUntilZero()
    {
        eqZeroEvent.WaitOne();
    }
    #endregion

    #地区私有方法
    私人无效AdjustZeroEvent()
    {
        如果(CURRENTCOUNT == 0)eqZeroEvent.Set();
        别的eqZeroEvent.Reset();
    }

    私人无效AdjustMaxEvent()
    {
        如果(CURRENTCOUNT< = MAXCOUNT)Monitor.Pulse(instanceLock);
        别人做{Monitor.Wait(instanceLock); }而(CURRENTCOUNT> MAXCOUNT);
    }
    #endregion
}
 

解决方案

退房CountdownLatch类在此<一个href="https://web.archive.org/web/20081003065703/http://msdn.microsoft.com/en-us/magazine/cc163427.aspx"相对=nofollow>杂志上的文章。

Perhaps it's too late at night, but I can't think of a nice way to do this.

I've started a bunch of asynchronous downloads, and I want to wait until they all complete before the program terminates. This leads me to believe I should increment something when a download starts, and decrement it when it finishes. But then how do I wait until the count is 0 again?

Semaphores sort of work in the opposite way in that you block when there are no resources available, not when they're all available (blocks when count is 0, rather than non-zero).


Based on the suggestions here, this is what I came up with. In addition to waiting until the count is 0, it will sleep if you spawn too many threads (count > max). Warning: This is not fully tested.

public class ThreadCounter
{
    #region Variables
    private int currentCount, maxCount;
    private ManualResetEvent eqZeroEvent;
    private object instanceLock = new object();
    #endregion

    #region Properties
    public int CurrentCount
    {
        get
        {
            return currentCount;
        }
        set
        {
            lock (instanceLock)
            {
                currentCount = value;
                AdjustZeroEvent();
                AdjustMaxEvent();
            }
        }
    }

    public int MaxCount
    {
        get
        {
            return maxCount;
        }
        set
        {
            lock (instanceLock)
            {
                maxCount = value;
                AdjustMaxEvent();
            }
        }
    }
    #endregion

    #region Constructors
    public ThreadCounter() : this(0) { }
    public ThreadCounter(int initialCount) : this(initialCount, int.MaxValue) { }
    public ThreadCounter(int initialCount, int maximumCount)
    {
        currentCount = initialCount;
        maxCount = maximumCount;
        eqZeroEvent = currentCount == 0 ? new ManualResetEvent(true) : new ManualResetEvent(false);
    }
    #endregion

    #region Public Methods
    public void Increment()
    {
        ++CurrentCount;
    }

    public void Decrement()
    {
        --CurrentCount;
    }

    public void WaitUntilZero()
    {
        eqZeroEvent.WaitOne();
    }
    #endregion

    #region Private Methods
    private void AdjustZeroEvent()
    {
        if (currentCount == 0) eqZeroEvent.Set();
        else eqZeroEvent.Reset();
    }

    private void AdjustMaxEvent()
    {
        if (currentCount <= maxCount) Monitor.Pulse(instanceLock);
        else do { Monitor.Wait(instanceLock); } while (currentCount > maxCount);
    }
    #endregion
}

解决方案

Check out the CountdownLatch class in this magazine article.

这篇关于.NET反转信号量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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