ThreadPool执行异步操作

使用ThreadPool_类执行异步任务

/*
 ThreadPool 类是一个静态类型类,使用ThreadPool 类执行异步时通常调用ThreadPool 的 QueueUserWorkItem 方法,这个方法有一个重载版本,如下:

public static bool QueueUserWorkItem(WaitCallback callBack);

public static bool QueueUserWorkItem(WaitCallback callBack, object state);

QueueUserWorkItem 方法接受一个WaitCallback 类型的委托作为回调方法以及可以选择传递一个线程池线程执行回调方法时所需要的数据对象。

WaitCallback 委托类型的定义如下:

public delegate void WaitCallback(object state);

线程池的QueueUserWorkItem方法在调用以后会立即返回,所传递的回调方法会有以后线程池线程执行。使用线程池线程执行异步任务代码如下:

 */

示例如下:

namespace 使用ThreadPool_类执行异步任务
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("主线程开始执行任务,线程ID:{0}",Thread.CurrentThread .ManagedThreadId);
            //使用ThreadPool.QueueUserWorkItem方法将一个异步任务添加到线程池任务队列中,
            //可以为线程池线程执行方法时传递一个数据对象
            //如果不需要传递数据uk恶意使用QueueUserWorkerItem只有WaitCallback一个参数类型的版本
            //或传递null
            ThreadPool.QueueUserWorkItem(state => {

                Console.WriteLine("线程池线程开始执行异步任务。线程ID:{0}",Thread.CurrentThread .ManagedThreadId );
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine(i);

                }

            },null );

            Console.WriteLine("主线程执行其他任务。线程ID:{0}",Thread .CurrentThread .ManagedThreadId );

            //使调用线程睡眠2000毫秒,等待线程池执行完成
            Thread.Sleep(2000);
            Console.WriteLine("主线程继续执行任务。线程ID:{0}",Thread.CurrentThread .ManagedThreadId);

        }
    }
}

线程池对线程的管理

/*
 CLR允许开发人员设置线程池需要创建的最大和最小工作者线程和IO线程,但是最好不要设置线程池的线程数,CLR对线程池的工作者线程和I/O线程的最大线程数设置了1000的默认值。我们可以使用线程池的如下方法对线程池数进行设置和获得最大线程池数和当前运行线程数之间的差值
 *
 * //设置可以同时处于活动状态的线程池的请求数目。
// 所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。
public static bool SetMaxThreads(int workerThreads, int completionPortThreads);
 // 发出新的请求时,在切换到管理线程创建和销毁的算法之前设置线程池按需创建的线程的最小数量。
public static bool SetMinThreads(int workerThreads, int completionPortThreads);
 //检索可以同时处于活动状态的线程池请求的数目。 所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。
 public static void GetMaxThreads(out int workerThreads, out int completionPortThreads);
//发出新的请求时,在切换到管理线程创建和销毁的算法之前检索线程池按需创建的线程的最小数量。
 public static void GetMinThreads(out int workerThreads, out int completionPortThreads);

 //获得最大线程池线程数和当前运行线程数之间的差值。
public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads);

 */

示例代码:

namespace 线程池对线程的管理
{
    class Program
    {
        static void Main(string[] args)
        {
            int worker, io;

            //获得线程池默认的最大线程数目。
            ThreadPool.GetMaxThreads(out worker ,out io);

            Console.WriteLine("1,CLR线程池默认最大线程数据,工作者线程数:{0},IO线程数:{1}",worker ,io );

            //设置线程池最大线程数
            ThreadPool.SetMaxThreads(100,100);
            ThreadPool.QueueUserWorkItem(state => {

                Thread.Sleep(2000);
                Console.WriteLine("4,线程池线程开始执行异步任务。线程ID:{0},",Thread.CurrentThread .ManagedThreadId );

            });

            Console.WriteLine("2,自定义设置线程池默认最大线程数据后,工作者线程数:{0},IO线程数: {1}:",worker ,io );
            //获得最大线程池线程数和当前运行线程数之间的差值
            ThreadPool.GetAvailableThreads(out worker ,out io );
            Console.WriteLine("3,获得最大线程池线程数和当前运行线程数之间的差值,工作者线程: {0},IO线程: {1}",worker ,io );
            Console.ReadKey();

        }
    }
}

/*

 线程池中的工作者线程是许多异步计算任务锁使用的线程,在线程池内部,工作者线程采用先入先出的算法将工作项从线程的全家队列中取出工作项并执行任务。在同一时刻可能有多个工作者线程从全局队列中取出工作项,因此所有工作者线程都会竞争一个线程同步锁,以保证两个或更多工作者线程不会在同一时刻取出工作项。
 *
 *
 * 线程池在创建工作者线程时,默认会创建ThreadPool.setminthreads方法锁设置的值。如果没有设置这个值,就会创建应用程序进程允许的使用的CUP数相同的工作者线程,这些工作这线程简史线程池任务的执行情况,得以动态的创建更多的或销毁空闲线程。
 * 

 */

线程执行上下文的流动

/*
 每个线程都有一个执行上下文,执行上下文包含了安全设置,宿主设置和逻辑调用上下文数据,CLR默认是把初始线程的执行上下文数据向辅助线程流动,初始线程在收集和复制执行上下文数据并传递到辅助线程时会带来性能的损失。如果不需要这些执行上下文数据可以使用system.threading.executioncontext类组织执行上下文数据的流转。
 * 常用方法::::::::::::
 *
 *         //     指示当前是否取消了执行上下文的流动。
        public static bool IsFlowSuppressed();
        //     恢复执行上下文在异步线程之间的流动。
        public static void RestoreFlow();
       //取消执行上下文在异步线程之间的流动。
        public static AsyncFlowControl SuppressFlow();

 */
namespace 线程执行上下文的流动
{
    class Program
    {
        static void Main(string[] args)
        {
            //把对象存储在调用逻辑上下文中,并将该对象与指定名称相关联
            System.Runtime.Remoting.Messaging.CallContext.LogicalSetData("key","这是主线程的执行上下文数据");

            Console.WriteLine("主线程执行上下文数据:{0}",System.Runtime .Remoting .Messaging .CallContext .LogicalGetData ("key"));

            //阻止主线程执行上下文数据的传递
            ExecutionContext.SuppressFlow();  //取消执行上下文在异步线程直接的流动
            Console.WriteLine("调用suppressFlow方法以后上下文传递流转是否被阻止:{0}",ExecutionContext .IsFlowSuppressed ().ToString ());

            ThreadPool.QueueUserWorkItem(state => {

                Console.WriteLine("执行上下文数据被阻止传递:{0}",System .Runtime .Remoting .Messaging .CallContext .LogicalGetData ("key"));

            });  //这里是没有输出的

            //恢复主线程执行上下文数据的传递
            ExecutionContext.RestoreFlow();//回复执行上下文在异步线程上的流动
            Console.WriteLine("调用RestoreFlow方法以后上下文传递流转是否被阻止:{0}",ExecutionContext .IsFlowSuppressed ().ToString ());

            ThreadPool.QueueUserWorkItem(state => {

                Console.WriteLine("执行上下文数据没有被阻止传递:{0}",System.Runtime.Remoting .Messaging .CallContext .LogicalGetData ("key"));

            });//将方法排入队列以便执行

            Console.ReadKey();

        }
    }
}

时间: 2024-10-11 23:22:05

ThreadPool执行异步操作的相关文章

C# 线程知识--使用ThreadPool执行异步操作

C# 线程知识--使用ThreadPool执行异步操作 在应用程序中有许多复杂的任务,对于这些任务可能需要使用一个或多个工作线程或I/O线程来协作处理,比如:定时任务.数据库数据操作.web服务.文件的处理等.这些任务可能会非常耗费时间,为了是用户界面能及时响应,就会启用一个其他线程来并行处理任务.线程的创建和销毁操作是非常昂贵的,过多的线程会带来内存资源的消耗以及操作系统调度可执行线程并执行上下文切换导致的时间消耗,所以过多线程会损坏应用程序的性能.如果创建过的线程能反复使用就能解决上面的一些

C#执行异步操作的几种方式比较和总结

原文出处: Durow(@Durow)   欢迎分享原创到伯乐头条 0×00 引言 之前写程序的时候在遇到一些比较花时间的操作例如HTTP请求时,总是会new一个Thread处理.对XxxxxAsync()之类的方法也没去了解过,倒也没遇到什么大问题.最近因为需求要求用DevExpress写界面,跑起来后发现比Native控件效率差好多.这才想到之前看到的“金科玉律”:不要在UI线程上执行界面无关的操作,因此集中看了下C#的异步操作,分享一下自己的比较和总结. 0×01 测试方法 IDE:VS2

[C#] 在 GUI 中执行异步操作

在 GUI 中执行异步操作 序 目录 一.在 GUI 程序中执行异步操作 下面通过窗体示例演示以下操作-点击按钮后:①将标签内容改成:“Doing”,并将按钮禁用(表示执行中):②线程挂起3秒(模拟耗时操作):③将标签内容改为:“Complete”,并启用按钮(表示执行完成): 1 public partial class Form1 : Form 2 { 3 public Form1() 4 { 5 InitializeComponent(); 6 } 7 8 private void btn

让playground执行异步操作

让playground执行异步操作 by 伍雪颖 import UIKit import XCPlayground XCPSetExecutionShouldContinueIndefinitely(continueIndefinitely: true) let url = NSURL(string: "http://httpbin.org/get") let getTask = NSURLSession.sharedSession().dataTaskWithURL(url!) {

[转]C# 线程知识--使用Task执行异步操作

C# 线程知识--使用Task执行异步操作 ??????在C#4.0之前需要执行一个复杂的异步操作时,只能使用CLR线程池技术来执行一个任务.线程池执行异步任务时,不知道任务何时完成,以及任务的在任务完成后不能获取到返回值.但是在C#4.0中引人了一个的任务(System.Threading.Tasks命名空间的类型)机制来解决异步操作完成时间和完成后返回值的问题. 1.使用Task类创建并执行简单任务 ??? 通过使用Task的构造函数来创建任务,并调用Start方法来启动任务并执行异步操作.

C# 线程知识--使用Task执行异步操作

来源:https://www.cnblogs.com/pengstone/archive/2012/12/23/2830238.html 在C#4.0之前需要执行一个复杂的异步操作时,只能使用CLR线程池技术来执行一个任务.线程池执行异步任务时,不知道任务何时完成,以及任务的在任务完成后不能获取到返回值.但是在C#4.0中引人了一个的任务(System.Threading.Tasks命名空间的类型)机制来解决异步操作完成时间和完成后返回值的问题. 1.使用Task类创建并执行简单任务 通过使用T

BroadcastReceiver 使用goAsync 执行异步操作

roadcastReceiver 生命周期 一个BroadcastReceiver 对象只有在被调用onReceive(Context, Intent)的才有效的,当从该函数返回后,该对象就无效的了,结束生命周期. 因此从这个特征可以看出,在所调用的onReceive(Context, Intent)函数里,不能有过于耗时的操作,不能使用线程来执行.对于耗时的操作,请start service来完成.因为当得到其他异步操作所返回的结果时,BroadcastReceiver 可能已经无效了.如果确

C# -- 使用线程池 ThreadPool 执行多线程任务

1. 使用线程池 1 class Program 2 { 3 static void Main(string[] args) 4 { 5 WaitCallback wc1 = s =>{ 6 Console.WriteLine("线程ID:{0},开始执行", Thread.CurrentThread.ManagedThreadId); 7 Stopwatch stw = new Stopwatch(); 8 stw.Start(); 9 long result = SumNum

C# -- 使用委托 delegate 执行异步操作

委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似. 与 C 中的函数指针不同,委托是面向对象的.类型安全的和保险的. 委托的类型由委托的名称定义. 1. 使用委托异步执行方法 class Program { public delegate void myWorking(string s); static void Main(string[] args) { Console.WriteLine("主线程开始....线程ID:{0}", Thread.CurrentT