代码改变世界

多线程实战(三)线程池

2015-09-05 16:18  xchit  阅读(424)  评论(0编辑  收藏  举报

 创建线程是昂贵的操作,所有为每个短暂的异步操作创建线程会产生显著的开销。为了解决这种短暂的任务,我们把它交给线程池(pooling);线程池可以成功地适应任何需要大量短暂开销资源情况。我们事先分配一定的资源,将这些资源放入到资源池。每次需要新的资源,只需要从池中获取一个,而不是创建一个新的。当资源不在被使用,就将其返回到池中;

ThreadPool

异步

CancellationTokenSource 类

RegisterWaitForSingleObject

 

ThreadPool

1.创建线程池

  static void Main1(string[] args)
        {
            ThreadPool.QueueUserWorkItem(AsyncOperation);
            Console.ReadKey();
        }


        private static void AsyncOperation(object state)
        {
            Console.WriteLine("参数状态: {0}", state ?? "(null)");
            Console.WriteLine("工作线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(2000);
        }

2.参数传递

 static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(AsyncOperation);
            ThreadPool.QueueUserWorkItem(AsyncOperation,"妹子");
            Console.ReadKey();
        }

        private static void AsyncOperation(object state)
        {
            Console.WriteLine("参数状态: {0}", state ?? "(null)");
            Console.WriteLine("工作线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(2000);
        }

3.另外的写法

static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(AsyncOperation);
            ThreadPool.QueueUserWorkItem(AsyncOperation,"妹子");


            ThreadPool.QueueUserWorkItem(state =>
            {
                Console.WriteLine("参数状态: {0}", state);
                Console.WriteLine("工作线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(TimeSpan.FromSeconds(2));
            }, "妹子");

         

            Console.ReadKey();
        }

        private static void AsyncOperation(object state)
        {
            Console.WriteLine("参数状态: {0}", state ?? "(null)");
            Console.WriteLine("工作线程ID: {0}", Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(2000);
        }

异步

 static void Main()
        {
            int threadId = 0;
            RunOnThreadPool poolDelegate = Test1;
            IAsyncResult r = poolDelegate.BeginInvoke(out threadId, Callback1, "异步回调参数");
            string result = poolDelegate.EndInvoke(out threadId, r);
            Console.WriteLine(result);
            Console.ReadKey();
        }


        private delegate string RunOnThreadPool(out int threadId);

        private static void Callback1(IAsyncResult ar)
        {
            Console.WriteLine("开始回调");
            Console.WriteLine("传入回掉的值: {0}", ar.AsyncState);
            Console.WriteLine("回掉是否是托管线程池: {0}", Thread.CurrentThread.IsThreadPoolThread);
            Console.WriteLine("线程iD: {0}", Thread.CurrentThread.ManagedThreadId);
        }


        private static string Test1(out int threadId)
        {
            Console.WriteLine("开始异步...");
            Console.WriteLine("是否是托管线程池: {0}", Thread.CurrentThread.IsThreadPoolThread);
            Thread.Sleep(TimeSpan.FromSeconds(2));
            threadId = Thread.CurrentThread.ManagedThreadId;
            return string.Format("池中线程ID: {0}", threadId);
        }

异步回调也是输入托管线程池

 

CancellationTokenSource 类

通知 CancellationToken,告知其应被取消。

static void Main(string[] args)
        {
            using (var cts = new CancellationTokenSource())
            {
                CancellationToken token = cts.Token;
                ThreadPool.QueueUserWorkItem(_ => AsyncOperation1(token));
                Thread.Sleep(TimeSpan.FromSeconds(2));
                cts.Cancel();
            }

            using (var cts = new CancellationTokenSource())
            {
                CancellationToken token = cts.Token;
                ThreadPool.QueueUserWorkItem(_ => AsyncOperation2(token));
                Thread.Sleep(TimeSpan.FromSeconds(2));
                cts.Cancel();
            }

            using (var cts = new CancellationTokenSource())
            {
                CancellationToken token = cts.Token;
                ThreadPool.QueueUserWorkItem(_ => AsyncOperation3(token));
                Thread.Sleep(TimeSpan.FromSeconds(2));
                cts.Cancel();
            }

            Thread.Sleep(TimeSpan.FromSeconds(2));

            Console.ReadKey();
        }

        static void AsyncOperation1(CancellationToken token)
        {
            Console.WriteLine("Starting the first task");
            for (int i = 0; i < 5; i++)
            {
                if (token.IsCancellationRequested)
                {
                    Console.WriteLine("The first task has been canceled.");
                    return;
                }
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
            Console.WriteLine("The first task has completed succesfully");
        }

        static void AsyncOperation2(CancellationToken token)
        {
            try
            {
                Console.WriteLine("Starting the second task");

                for (int i = 0; i < 5; i++)
                {
                    token.ThrowIfCancellationRequested();
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                }
                Console.WriteLine("The second task has completed succesfully");
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("The second task has been canceled.");
            }
        }

        private static void AsyncOperation3(CancellationToken token)
        {
            bool cancellationFlag = false;
            token.Register(() => cancellationFlag = true);
            Console.WriteLine("Starting the third task");
            for (int i = 0; i < 5; i++)
            {
                if (cancellationFlag)
                {
                    Console.WriteLine("The third task has been canceled.");
                    return;
                }
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
            Console.WriteLine("The third task has completed succesfully");
        }

 

RegisterWaitForSingleObject

RegisterWaitForSingleObject提供了一些简单的线程间交互

static void Main(string[] args)
        {
            RunOperations(TimeSpan.FromSeconds(5));
            RunOperations(TimeSpan.FromSeconds(7));
            Console.ReadKey();
        }

        static void RunOperations(TimeSpan workerOperationTimeout)
        {
            using (var evt = new ManualResetEvent(false))
            using (var cts = new CancellationTokenSource())
            {
                Console.WriteLine("注册超时行为...");
                var worker = ThreadPool.RegisterWaitForSingleObject(evt,
                    (state, isTimedOut) => WorkerOperationWait(cts, isTimedOut), null, workerOperationTimeout, true);

                Console.WriteLine("启动长时间运行...");

                ThreadPool.QueueUserWorkItem(_ => WorkerOperation(cts.Token, evt));

                Thread.Sleep(workerOperationTimeout.Add(TimeSpan.FromSeconds(2)));
                worker.Unregister(evt);
            }
        }

        static void WorkerOperation(CancellationToken token, ManualResetEvent evt)
        {
            for(int i = 0; i < 6; i++)
            {
                if (token.IsCancellationRequested)
                {
                    return;
                }
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
            evt.Set();
        }

        static void WorkerOperationWait(CancellationTokenSource cts, bool isTimedOut)
        {
            if (isTimedOut)
            {
                cts.Cancel();
                Console.WriteLine("超时取消.");
            }
            else
            {
                Console.WriteLine("操作成功.");
            }
        }