zoukankan      html  css  js  c++  java
  • .net 4.0新特性CountDownEvent

    也称为反Semaphore 作用:统计其他线程结束工作,监听计数为0时,触发操作.
    与Semaphore形成对比,Semaphore有最大资源数,当计数为0时(即资源不够用时)则阻塞线程
    1.Semaphore
    初始化时,资源为0,调用Release方法释放资源

    using System;
    using System.Threading;
    
    public class Example
    {
        // A semaphore that simulates a limited resource pool.
        //
        private static Semaphore _pool;
    
        // A padding interval to make the output more orderly.
        private static int _padding;
    
        public static void Main()
        {
            // Create a semaphore that can satisfy up to three
            // concurrent requests. Use an initial count of zero,
            // so that the entire semaphore count is initially
            // owned by the main program thread.
            //
            _pool = new Semaphore(0, 3);
    
            // Create and start five numbered threads. 
            //
            for (int i = 1; i <= 5; i++)
            {
                Thread t = new Thread(new ParameterizedThreadStart(Worker));
    
                // Start the thread, passing the number.
                //
                t.Start(i);
            }
    
            // Wait for half a second, to allow all the
            // threads to start and to block on the semaphore.
            //
            Thread.Sleep(500);
    
            // The main thread starts out holding the entire
            // semaphore count. Calling Release(3) brings the 
            // semaphore count back to its maximum value, and
            // allows the waiting threads to enter the semaphore,
            // up to three at a time.
            //
            Console.WriteLine("Main thread calls Release(3).");
            _pool.Release(3);
    
            Console.WriteLine("Main thread exits.");
        }
    
        private static void Worker(object num)
        {
            // Each worker thread begins by requesting the
            // semaphore.
            Console.WriteLine("Thread {0} begins " +
                "and waits for the semaphore.", num);
            _pool.WaitOne();
    
            // A padding interval to make the output more orderly.
            int padding = Interlocked.Add(ref _padding, 100);
    
            Console.WriteLine("Thread {0} enters the semaphore.", num);
    
            // The thread's "work" consists of sleeping for 
            // about a second. Each thread "works" a little 
            // longer, just to make the output more orderly.
            //
            Thread.Sleep(1000 + padding);
    
            Console.WriteLine("Thread {0} releases the semaphore.", num);
            Console.WriteLine("Thread {0} previous semaphore count: {1}",
                num, _pool.Release());
        }
    }
    
    可以看到同时进入三个线程
    image

    2.CountDownEvent
    初始化当前线程计数即为1,然后在其他线程运行前调用AddCount进行计数,执行完毕后调用Signal方法减少计数.等所有线程计数后,还需要在当前线程中调用Signal,等所有工作完成计数为0时,Wait方法将不再阻塞
    using System;
    using System.Collections.Generic;
    using System.Threading;
    using System.Threading.Tasks;
    
    class CancelableCountdowEvent
    {
        class Data
        {
            public int Num { get; set; }
            public Data(int i) { Num = i; }
            public Data() { }
        }
    
        class DataWithToken
        {
            public CancellationToken Token { get; set; }
            public Data Data { get; private set; }
            public DataWithToken(Data data, CancellationToken ct)
            {
                this.Data = data;
                this.Token = ct;
            }
        }
        static IEnumerable<Data> GetData()
        {
            return new List<Data>() { new Data(1), new Data(2), new Data(3), new Data(4), new Data(5) };
        }
        static void ProcessData(object obj)
        {
            DataWithToken dataWithToken = (DataWithToken)obj;
            if (dataWithToken.Token.IsCancellationRequested)
            {
                Console.WriteLine("Canceled before starting {0}", dataWithToken.Data.Num);
                return;
            }
    
            for (int i = 0; i < 1000; i++)
            {
                // Increase this value to slow down the program.
                Thread.SpinWait(100000);
            }
            Console.WriteLine("Processed {0}", dataWithToken.Data.Num);
        }
    
        static void Main(string[] args)
        {
            EventWithCancel();
    
            Console.WriteLine("Press enter to exit.");
            Console.ReadLine();
        }
    
        static void EventWithCancel()
        {
            IEnumerable<Data> source = GetData();
            CancellationTokenSource cts = new CancellationTokenSource();
    
            //Enable cancellation request from a simple UI thread.
            Task.Factory.StartNew(() =>
            {
                if (Console.ReadKey().KeyChar == 'c')
                    cts.Cancel();
            });
    
            // Event must have a count of at least 1
            CountdownEvent e = new CountdownEvent(1);
    
    
            // fork work:
            foreach (Data element in source)
            {
                DataWithToken item = new DataWithToken(element, cts.Token);
                // Dynamically increment signal count.
                e.AddCount();
                ThreadPool.QueueUserWorkItem(delegate(object state)
                {
                    ProcessData(state);
                    //if (!cts.Token.IsCancellationRequested)
                    e.Signal();
                },
                 item);
            }
            //// Decrement the signal count by the one we added
            //// in the constructor.
            e.Signal();
    
            //// The first element could be run on this thread.
    
            //// Join with work or catch cancellation.
            try
            {
                e.Wait(cts.Token);
            }
            catch (OperationCanceledException oce)
            {
                if (oce.CancellationToken == cts.Token)
                {
                    Console.WriteLine("User canceled.");
                }
                else throw; //We don't know who canceled us!
            }
            e.Dispose();
    
            //... 
        } //end method
    } //end class
    

    参考:

    http://www.cnblogs.com/shanyou/archive/2009/10/27/1590890.html
    http://blogs.msdn.com/b/pfxteam/archive/2008/06/21/8629821.aspx

    http://msdn.microsoft.com/zh-cn/magazine/cc163427.aspx

  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    初识面向对象编程(Object Oriented Programming,OOP)
    详述WebLogic反序列化远程命令执行漏洞的处理过程,云和恩墨技术通讯精选
    分布式监控系统zipkin介绍
    Uncaught TypeError: Cannot set property 'render' of undefined
    python PIL的Image.resize()和Image.thumbnail()函数的区别
    dump 组合索引存储null值
    史上最全MySQL锁机制
    Dump 组合索引
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/1755525.html
Copyright © 2011-2022 走看看