C#/.NET 对ManualResetEvent的重新封装MutipleThreadResetEvent

点击此进入C#/.NET异步编程【目录】


看这篇文章之前,你必须对ManualResetEvent有一定的了解才行。

ManualResetEvent主要被用作线程同步,线程等待。它可以通知一个或多个正在等待的线程已发生事件,允许线程通过发信号互相通信,来控制线程是否可心访问资源

当一个线程开始一个活动(此活动必须完成后,其他线程才能开始)时,它调用 Reset 以将 ManualResetEvent 置于非终止状态。此线程可被视为控制 ManualResetEvent。调用 ManualResetEvent 上的WaitOne 的线程将阻止,并等待信号。当控制线程完成活动时,它调用 Set 以发出等待线程可以继续进行的信号。并释放所有等待线程。


接下来将会对ManualResetEvent进行再封装,封装成一个可同时控制多个线程进行同步、等待等操作。封装及调用实例如下:

    public class MutipleThreadResetEvent : IDisposable
    {
        private readonly ManualResetEvent done;

        private readonly int total;

        private long current;

        public MutipleThreadResetEvent(int total)
        {
            this.total = total;
            current = total;
            done = new ManualResetEvent(initialState: false);
        }

        /// 
        /// 释放一个
        /// 
        public void SetOne()
        {
            if (Interlocked.Decrement(ref current) == 0L)
            {
                done.Set();
            }
        }

        public void WaitAll()
        {
            done.WaitOne();
        }

        public void Dispose()
        {
            ((IDisposable)done).Dispose();
        }
    }

调用:

        /// 
        /// 调用
        /// 
        public void Use()
        {
            CancellationTokenSource cts = new CancellationTokenSource();//线程取消
            List<int> lsInt = new List<int>() { 1, 2, 3, 4, 5, 6 };

            int num = lsInt.Count;
            var maxThread = num > 5 ? 5 : num;
            Semaphore semaphore = new Semaphore(maxThread, maxThread);
            MutipleThreadResetEvent mutipleThreadReset = new MutipleThreadResetEvent(num);
            

            foreach (var valueItem in lsInt)
            {
                semaphore.WaitOne();//信号量控制最大运行线程
                Task.Factory.StartNew((obj) =>
                {
                    try
                    {
                        if (!cts.IsCancellationRequested)
                        {
                            //...
                        }
                    }
                    catch (ThreadAbortException) { cts.Cancel(); }
                    finally
                    {
                        semaphore.Release();
                        mutipleThreadReset.SetOne();
                    }
                }, valueItem, cts.Token);

                mutipleThreadReset.WaitAll();
            }
        }

你可能感兴趣的:(【C#/.NET,异步编程】)