C#线程池

 class Program
    {
        // 使用BeginXXX/EndXXX和IAsyncResult对象的方式被称为异步编程模型(APM模式)
        delegate string RunOnThreadPool(out int threadId);

        static void Main(string[] args)
        {
            int threadId = 0;
            // 给委托变量赋值
            RunOnThreadPool poolDelegate = Test;

            var t = new Thread(() => { Test(out threadId); });
            t.Start();
            t.Join();
            Console.WriteLine($"1.返回的线程Id:{threadId}");

            // 通过调用委托变量的BeginInvoke方法来运行委托(执行Test方法)
            IAsyncResult ar = poolDelegate.BeginInvoke(out threadId, Callback, "异步委托调用");
            ar.AsyncWaitHandle.WaitOne();
            // 调用委托的EndInvoke会等待异步操作(Test方法)完成
            // 异步操作执行完成之后,开始执行回掉函数;异步操作和回掉函数很可能会被线程池中同一个工作线程执行
            string result = poolDelegate.EndInvoke(out threadId, ar);
            Console.WriteLine($"2.返回的线程Id:{threadId}");
            Console.WriteLine($"返回值:{result}");

            Console.ReadKey();
        }

        static void Callback(IAsyncResult ar)
        {
            Console.WriteLine("开始执行回掉函数...");
            Console.WriteLine($"异步状态:{ar.AsyncState}");
            Console.WriteLine($"是否为线程池中的线程:{Thread.CurrentThread.IsThreadPoolThread}");
            Console.WriteLine($"线程池工作线程Id:{Thread.CurrentThread.ManagedThreadId}");
        }

        static string Test(out int threadId)
        {
            Console.WriteLine("开始测试方法...");
            Console.WriteLine($"是否为线程池中的线程:{Thread.CurrentThread.IsThreadPoolThread}");
            Thread.Sleep(TimeSpan.FromSeconds(2));
            threadId = Thread.CurrentThread.ManagedThreadId;
            return $"线程Id:{threadId}";
        }
    }

  向线程池中放入异步操作

 class Program
    {
        static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(AsyncOperation);
            Thread.Sleep(TimeSpan.FromSeconds(2));
            ThreadPool.QueueUserWorkItem(AsyncOperation, "async state");
            Thread.Sleep(TimeSpan.FromSeconds(2));

            ThreadPool.QueueUserWorkItem(state =>
            {
                Console.WriteLine($"操作状态:{state}");
                Console.WriteLine($"工作线程Id:{Thread.CurrentThread.ManagedThreadId}");
                Thread.Sleep(TimeSpan.FromSeconds(2));
            }, "lambda state");

            const int x = 1;
            const int y = 2;
            const string lambdaState = "lambda state 2";
            // 使用闭包机制,无需传递lambda表达式的状态参数
            ThreadPool.QueueUserWorkItem(_ =>
            {
                Console.WriteLine($"操作状态:{x + y},{lambdaState}");
                Console.WriteLine($"工作线程Id:{Thread.CurrentThread.ManagedThreadId}");
                Thread.Sleep(TimeSpan.FromSeconds(2));
            });

            Console.ReadKey();
        }

        static void AsyncOperation(object state)
        {
            Console.WriteLine($"操作状态:{state ?? "(null)"}");
            Console.WriteLine($"工作线程Id:{Thread.CurrentThread.ManagedThreadId}");
            Thread.Sleep(TimeSpan.FromSeconds(2));
        }
    }

  线程池与并行度:

 static void Main(string[] args)
        {
            int threadCount = 500;
            var sw = new Stopwatch();
            sw.Start();
            UseThreads(threadCount);
            sw.Stop();
            Console.WriteLine($"手动创建线程执行操作耗时:{sw.ElapsedMilliseconds}");

            sw.Reset();
            sw.Start();
            UseThreadPool(threadCount);
            sw.Stop();
            Console.WriteLine($"使用线程池执行操作耗时:{sw.ElapsedMilliseconds}");

            Console.ReadKey();
        }

        static void UseThreads(int threadCount)
        {
            using (CountdownEvent cdEvt = new CountdownEvent(threadCount))
            {
                Console.WriteLine("开始创建线程");
                for (int i = 0; i < threadCount; i++)
                {
                    var thread = new Thread(() =>
                    {
                        Console.WriteLine($"是否为线程池中的线程:{Thread.CurrentThread.IsThreadPoolThread},线程Id:{Thread.CurrentThread.ManagedThreadId}");
                        Thread.Sleep(TimeSpan.FromSeconds(0.1));
                        cdEvt.Signal();
                    });
                    thread.Start();
                }
                cdEvt.Wait();
                Console.WriteLine();
            }
        }

        /// <summary>
        /// 线程池的用途是执行时间短的操作,使用线程池可以减少并行度消耗及节省操作系统资源
        /// </summary>
        /// <param name="threadCount"></param>
        static void UseThreadPool(int threadCount)
        {
            using (CountdownEvent cdEvt = new CountdownEvent(threadCount))
            {
                Console.WriteLine("开始使用线程池");
                for (int i = 0; i < threadCount; i++)
                {
                    ThreadPool.QueueUserWorkItem(_ =>
                    {
                        Console.WriteLine($"是否为线程池中的线程:{Thread.CurrentThread.IsThreadPoolThread},线程Id:{Thread.CurrentThread.ManagedThreadId}");
                        Thread.Sleep(TimeSpan.FromSeconds(0.1));
                        cdEvt.Signal();
                    });
                }
                cdEvt.Wait();
                Console.WriteLine();
            }
        }

        //在收到信号特定次数后取消阻止等待线程的同步基元
        //可以使用取消令牌取消等待操作
        //创建实例后,可以递增信号计数
        //在 Reset 方法调用返回 Wait 后,可以重用实例
        public void Test()
        {
            IEnumerable<Data> source = GetData();
            using (CountdownEvent e = new CountdownEvent(1))
            {
                foreach (Data element in source)
                {
                    e.AddCount();
                    ThreadPool.QueueUserWorkItem(delegate (object state)
                    {
                        try
                        {
                            ProcessData(state);
                        }
                        finally
                        {
                            e.Signal();
                        }
                    },
         element);
                }
            }
        }
        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 < 10000; i++)
            {
                if (dataWithToken.Token.IsCancellationRequested)
                {
                    Console.WriteLine("Cancelling while executing {0}", dataWithToken.Data.Num);
                    return;
                }

                Thread.SpinWait(100000);
            }
            Console.WriteLine("Processed {0}", dataWithToken.Data.Num);
        }

        static void EventWithCancel()
        {
            IEnumerable<Data> source = GetData();
            CancellationTokenSource cts = new CancellationTokenSource();
            Task.Factory.StartNew(() =>
            {
                if (Console.ReadKey().KeyChar == 'c') cts.Cancel();
            });
            CountdownEvent e = new CountdownEvent(1);

            foreach (Data element in source)
            {
                DataWithToken item = new DataWithToken(element, cts.Token);
                e.AddCount();
                ThreadPool.QueueUserWorkItem(delegate (object state)
                {
                    ProcessData(state);
                    if (!cts.Token.IsCancellationRequested)
                        e.Signal();
                },
             item);
            }
            e.Signal();

            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!
                }
            }
            finally
            {
                e.Dispose();
                cts.Dispose();
            }
        }
    }
    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 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();
            }

            Console.ReadKey();
        }
        static void AsyncOperation1(CancellationToken token)
        {
            Console.WriteLine("启动第一个异步操作");
            for (int i = 0; i < 5; i++)
            {
                // 轮询检查IsCancellationRequested属性
                if (token.IsCancellationRequested)
                {
                    Console.WriteLine("第一个异步操作被取消啦~~~");
                    return;
                }
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
            Console.WriteLine("第一个异步操作完成");
        }
        static void AsyncOperation2(CancellationToken token)
        {
            try
            {
                Console.WriteLine("启动第二个异步操作");
                for (int i = 0; i < 5; i++)
                {
                    // 抛出异常,取消操作时,通过操作之外的代码来处理
                    token.ThrowIfCancellationRequested();
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                }
                Console.WriteLine("第二个异步操作完成");
            }
            catch (OperationCanceledException ex)
            {
                Console.WriteLine($"第二个异步操作被取消,异常消息:{ex.Message}");
            }
        }
        static void AsyncOperation3(CancellationToken token)
        {
            bool cancellationFlag = false;
            // 注册回调函数,当操作被取消时,线程池将调用该回调函数
            token.Register(() => { cancellationFlag = true; });
            Console.WriteLine("启动第三个异步操作");
            for (int i = 0; i < 5; i++)
            {
                if (cancellationFlag)
                {
                    Console.WriteLine("第三个异步操作被取消啦~~~");
                    return;
                }
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }
            Console.WriteLine("第三个异步操作完成");
        }

  在线程池中使用等待事件处理器及超时

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

        static void RunOperation(TimeSpan workerOperationTs)
        {
            using (var evt = new ManualResetEvent(false))
            using (var cts = new CancellationTokenSource())
            {
                Console.WriteLine("注册操作超时的方法...");
                var worker = ThreadPool.RegisterWaitForSingleObject(evt,
                    (state, isTimeout) => WorkerOperationWait(cts, isTimeout),
                    null, workerOperationTs, true);
                Console.WriteLine("开始长时间操作...");
                ThreadPool.QueueUserWorkItem(_ =>
                {
                    WorkerOperation(cts.Token, evt);
                });

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

        static void WorkerOperation(CancellationToken token, ManualResetEvent evt)
        {
            for (int i = 0; i < 6; i++)
            {
                if(token.IsCancellationRequested)
                {
                    Console.WriteLine("异步操作被取消");
                    return;
                }
                Thread.Sleep(TimeSpan.FromSeconds(1));
            }

            evt.Set();
        }

        static void WorkerOperationWait(CancellationTokenSource cts,bool isTimeout)
        {
            if(isTimeout)
            {
                cts.Cancel();
                Console.WriteLine("异步操作超时并被取消了");
            }
            else
            {
                Console.WriteLine("异步操作完成"); 
            }
        }

  

posted @ 2020-05-30 16:50  石shi  阅读(402)  评论(0编辑  收藏  举报