使用线程池(1)

在线程池中调用委托

为什么要使用线程池?

创建线程是昂贵的操作,所以为每个短暂的异步操作创建线程会产生显著的开销。为了解决该问题,有一个常用的方式叫(pooling)。线程池可以成功的适应于任何需要大量短暂的开销大的资源的情形。

注意事项:

  • 每个CLR都有一个线程池实例;
  • 保持线程中的操作都是短暂的是非常重要的。不要在线程池中放入长时间运行的操作或者阻塞线程,否则会产生性能问题和非常难以调试的错误;
  • 线程池中的工作线程都是后台线程。

以下是代码实践:

using System;
using System.Threading;

namespace 在线程池中调用委托
{
    internal class Program
    {
        private static void Main()
        {
            var threadId = 0;

            RunOnThreadPool poolDelegate = Test;

            //线程的构造函数只接受一个无返回值得方法,所以用lambda表达式将Test方法的调用包起来。
            var t = new Thread(() => Test(out threadId));

            t.Start();
            t.Join();

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

            Console.WriteLine("Thread id: {0}", threadId);

            /*委托的异步调用,在线程池的子线程中执行委托Test函数和Callback函数在线程池中很可能在同一线程上执行,         
             * BeginInvoke接受一个回调函数,异步操作完成后调用回调函数,"a delegate asynchrous call"用户自定义
             * 状态传递给回调函数
             */
            var r = poolDelegate.BeginInvoke(out threadId, Callback, "a delegate asynchrous call");
            r.AsyncWaitHandle.WaitOne();//等待操作完成,可省略,因为EndInvoke方法会等待异步操作的完成

            /*Test异步调用完成后,立即执行下一步操作,不等待回调函数的完成,
             * EndInvoke方法会等待异步操作的完成,
             * EndInvoke方法会将任何未处理的异常抛到调用线程里,所以BeginEnd要配对使用。
             */
            var result = poolDelegate.EndInvoke(out threadId, r);

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

            Console.WriteLine("Thread pool worker thread id: {0}", threadId);
            Console.WriteLine(result);

            //Thread.Sleep(TimeSpan.FromSeconds(2));
            Console.ReadKey();
        }

        private delegate string RunOnThreadPool(out int threadId);

        private static void Callback(IAsyncResult ar)
        {
            Console.WriteLine("Starting a callback...");
            Console.WriteLine("State passed to a callback: {0}", ar.AsyncState);
            Console.WriteLine("Is thread pool thread: {0}", Thread.CurrentThread.IsThreadPoolThread);
            Console.WriteLine("Thread pool worker thread id: {0}", Thread.CurrentThread.ManagedThreadId);
        }

        private static string Test(out int threadId)
        {
            Console.WriteLine("Starting...");
            Console.WriteLine("Is thread pool thread: {0}", Thread.CurrentThread.IsThreadPoolThread);
            Thread.Sleep(TimeSpan.FromSeconds(2));
            threadId = Thread.CurrentThread.ManagedThreadId;
            return string.Format("Thread pool worker id was: {0}", threadId);
        }
    }
}

总结

使用BeginOperationName/EndOperationName方法和.NET中的IAsyncResult对象等方式被称为异步编程模型(APM),这样的方法称为异步方法。现代编程中更推荐任务并行库(Task Parallel Library简称TPL)

备注:学习《Multithreading in C# 5.0 Cookbook》Eugene Agafonov著的总结,以备日后查询。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值