C#多线程开发-线程池03

简介: C#多线程开发-线程池03

你好,我是阿辉。


前面2篇文章介绍了线程的基础知识和线程同步,下面我们来一起认识学习下,线程池的使用。


线程池


创建线程是昂贵的操作,所以为每个短暂的异步操作创建线程会产生显著的开销。一般情况下,都会使用池,也就是线程池进行管理。


线程池可以成功地适应于任何需要大量短暂的开销大的资源。事先分配一定的资源,将这些资源放入到资源池中。每次需要新的资源,只需从池中获取一个,不需要创建新的,当该资源不再被使用时,就将其返回到池中。



在.NET中,线程池可以使用ThreadPool类型,受.NET通用语言运行时(CLR)管理。每个CLR都有一个线程池实例。ThreadPool类型拥有一个QueueUserWorkItem静态方法。



该方法接收一个委托,代表用户自定义的一个异步操作。该方法被调用后,委托会进入到内部队列中,如果线程池中没有任何线程,将创建一个新的工作线程并将队列中第一个委托放入到该工作线程中。


保持在线程中的操作都是短暂的是非常重要的。不要在线程池中放入长时间运行的操作,或者阻塞工作线程。 这将导致所有工作线程变的繁忙,从而无法服务用户操作。这会导致性能问题和非常难以调式的错误。



在线程池中,如果停止向其放置新操作时,线程池最终会删除一定时间后过期的不再使用的线程。这将释放所有那些不再的系统资源。



线程池的用途是执行运行时间短的操作。使用线程池可以减少并行度耗费及节省操作系统资源。

线程池中的工作线程都是后台线程。这意味着当所有的前台线程(包括主线程)完成后,所有的后台线程将停止工作。


线程池中异步的使用

  class Program
    {
        private delegate string RunOnThreadPool(out int threadId);                  //声明委托
        private static void Callback(IAsyncResult ar)
        {
            Console.WriteLine("触发回调");
            Console.WriteLine("异步状态:" + ar.AsyncState);
            Console.WriteLine("是否是线程池的线程:" + Thread.CurrentThread.IsThreadPoolThread);
            Console.WriteLine("ThreadId:" + Thread.CurrentThread.ManagedThreadId);
        }
        private static string Test(out int threadId)
        {
            Console.WriteLine("Test开始");
            Console.WriteLine("是否是线程池的线程:" + Thread.CurrentThread.IsThreadPoolThread);
            Thread.Sleep(TimeSpan.FromSeconds(2));
            threadId = Thread.CurrentThread.ManagedThreadId;
            return "ThreadId:" + 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("Thread ID="+threadId);
            IAsyncResult ar=poolDelegate.BeginInvoke(out threadId,Callback,"测试是否可以回调");
            ar.AsyncWaitHandle.WaitOne();
            string result=poolDelegate.EndInvoke(out threadId,ar);
            Console.WriteLine("ID:"+threadId);
            Console.WriteLine("结果:"+result);
            Console.ReadKey();
        }       
    }



执行后可以看到实际的显示结果。



由于线程的构造函数只能接受一个无任何返回结果的方法,所以这里使用了lambda表达式来将对Test方法的调用包起来。



上面是一个很标准的在线程池中使用委托的例子,也可以学习到具体线程池的应用。可以看到当第一次线程池中没有线程时,打印出来线程10不在线程中,当第二次在线程池中时,后面异步回调显示出来的结果就是再次调用的线程11。



BeginInvoke方法接受一个回调函数,该回调函数会在异步操作完成后会被调用,并且一个用户自定义的状态会传给该回调函数。该状态通常用于区分异步调用,是一个实现了IAsyncResult接口的result对象。BeginInvoke立即返回结果,当线程池中的工作线程在执行异步操作时,仍允许继续其他工作,可以通过result对象的IsCompleted属性轮询结果。当操作完成后,会得到一个结果,可以通过委托调用EndInvoke方法,将IAsyncResult对象传递给委托参数。



上面这句话其实主要是讲解委托在线程池中的应用,如果你想得到某个线程的返回结果,就得使用这种异步委托来实现。



在线程池中使用委托时,调用EndInvoke方法是非常重要的。该方法会将任何未处理的异常抛回到调用线程中。当使用这种异步API时,请确保始终调用Begin和End方法。



上面使用的Begin/End方法和.NET中的IAsyncResult对象等方式被称为异步编程模型(APM模式),这样的方法叫异步方法。


线程池中还有一个有用的方法:ThreadPool.RegisterWaitForSingleObject。该方法允许我们将回调函数放入线程池中的队列中。当提供的等待事件处理器收到信号或发生超时时,该回调函数将被调用。


在线程池中使用BackgroundWorker组件,可以显示地指出后台工作线程支持取消操作及操作进度的通知。此时可以使用事件语法。


事件表示了一些通知的源或当通知到达时会有所响应的一系列订阅者。


这种就是基于事件的异步模式(EAP),就是启动一个异步操作然后订阅给不同的事件,这些事件在该操作执行时会被触发。




目录
相关文章
|
10天前
|
前端开发 JavaScript 安全
C#一分钟浅谈:Blazor WebAssembly 开发
Blazor WebAssembly 是一个客户端框架,允许开发者使用C#和Razor语法构建Web应用。本文介绍了Blazor WebAssembly的基本概念、常见问题及解决方案,包括路由配置、数据绑定、异步操作、状态管理和性能优化等方面的内容,并分享了一些易错点及如何避免的方法。希望这些内容能帮助你在Blazor WebAssembly开发中少走弯路,提高开发效率。
84 51
|
24天前
|
监控 安全 Java
在 Java 中使用线程池监控以及动态调整线程池时需要注意什么?
【10月更文挑战第22天】在进行线程池的监控和动态调整时,要综合考虑多方面的因素,谨慎操作,以确保线程池能够高效、稳定地运行,满足业务的需求。
102 38
|
8天前
|
开发框架 缓存 .NET
C# 一分钟浅谈:Blazor Server 端开发
Blazor Server 是基于 ASP.NET Core 的框架,允许使用 C# 和 Razor 语法构建交互式 Web 应用。本文介绍 Blazor Server 的基本概念、快速入门、常见问题及解决方案,帮助开发者快速上手。涵盖创建应用、基本组件、数据绑定、状态管理、跨组件通信、错误处理和性能优化等内容。
21 1
|
9天前
|
缓存 C# 开发者
C# 一分钟浅谈:Blazor Server 端开发
本文介绍了 Blazor Server,一种基于 .NET 的 Web 开发模型,允许使用 C# 和 Razor 语法构建交互式 Web 应用。文章从基础概念、创建应用、常见问题及解决方案、易错点及避免方法等方面详细讲解,帮助开发者快速上手并提高开发效率。
30 2
|
18天前
|
测试技术 Go C#
C#一分钟浅谈:ReSharper 插件增强开发效率
【10月更文挑战第25天】ReSharper 是 JetBrains 开发的一款 Visual Studio 插件,旨在提高 .NET 开发者的生产力。它通过代码分析、重构、导航等功能,帮助开发者避免常见错误,提升代码质量和开发效率。本文将通过具体代码案例,详细介绍 ReSharper 的常见功能及其应用。
35 1
|
22天前
|
Java
线程池内部机制:线程的保活与回收策略
【10月更文挑战第24天】 线程池是现代并发编程中管理线程资源的一种高效机制。它不仅能够复用线程,减少创建和销毁线程的开销,还能有效控制并发线程的数量,提高系统资源的利用率。本文将深入探讨线程池中线程的保活和回收机制,帮助你更好地理解和使用线程池。
47 2
|
24天前
|
Prometheus 监控 Cloud Native
JAVA线程池监控以及动态调整线程池
【10月更文挑战第22天】在 Java 中,线程池的监控和动态调整是非常重要的,它可以帮助我们更好地管理系统资源,提高应用的性能和稳定性。
63 4
|
24天前
|
Prometheus 监控 Cloud Native
在 Java 中,如何使用线程池监控以及动态调整线程池?
【10月更文挑战第22天】线程池的监控和动态调整是一项重要的任务,需要我们结合具体的应用场景和需求,选择合适的方法和策略,以确保线程池始终处于最优状态,提高系统的性能和稳定性。
96 2
|
24天前
|
C# Python
使用wxpython开发跨平台桌面应用,对wxpython控件实现类似C#扩展函数处理的探究
【10月更文挑战第30天】使用 `wxPython` 开发跨平台桌面应用时,可以通过创建辅助类来模拟 C# 扩展函数的功能。具体步骤包括:1. 创建辅助类 `WxWidgetHelpers`;2. 在该类中定义静态方法,如 `set_button_color`;3. 在应用中调用这些方法。这种方法提高了代码的可读性和可维护性,无需修改 `wxPython` 库即可为控件添加自定义功能。但需要注意显式调用方法和避免命名冲突。
|
1月前
|
JSON C# 开发者
C#语言新特性深度剖析:提升你的.NET开发效率
【10月更文挑战第15天】C#语言凭借其强大的功能和易用性深受开发者喜爱。随着.NET平台的演进,C#不断引入新特性,如C# 7.0的模式匹配和C# 8.0的异步流,显著提升了开发效率和代码可维护性。本文将深入探讨这些新特性,助力开发者在.NET开发中更高效地利用它们。
34 1