精华内容
下载资源
问答
  • c#threadpool
    2022-07-28 16:42:50

    一.设置线程池的最大最先线程数量

     ThreadPool.SetMaxThreads(16,16);// 设置线程池最大线程数量
     ThreadPool.SetMinThreads(8, 8);
     ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);// 获取线程池最大线程数量
     ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads);

    二.简单使用线程池

    
    // 将线程丢进线程池,参数是线程要做的事情            
    ThreadPool.QueueUserWorkItem(t =>
    {
          DoSomething("threadPool");
    });

    三.使用ManualResetEvent做到做到线程池的线程等待

    ManualResetEvent manualResetEvent = new ManualResetEvent(false);// false代表线程会阻塞
    ThreadPool.QueueUserWorkItem(t =>
    {
         DoSomething("threadPool");
         // 等到这个线程完成这件事情后,就设置manualResetEvent变为true
         manualResetEvent.Set();// Set过后(manualResetEvent 变为true),WaitOne就会过去了
         // manualResetEvent.Reset();
    });
    manualResetEvent.WaitOne();// 只要没有Set回去,线程会一直卡在这里
    // 一般来说不要阻塞线程池的线程,因为程序在运行过程中会出现一些问题(死锁问题)
    // 如果非要使用那么一定要set回去

    四.使用ManualResetEvent出现死锁的情况

                // 问题就是在k等于18的时候线程会死锁
                for (int i = 0; i < 20; i++)
                {
                    int k = i;
                    ThreadPool.QueueUserWorkItem(t =>
                    {
                        Console.WriteLine(k);
                        if (k < 18)
                        {
                            // 因为我设置最大线程数只有16个,线程池里面的线程到达16个后就不会往后走了(此时线程都在使用中),就不会到达Set方法,所以就会死锁
                            manualResetEvent.WaitOne();// 等待
                        }
                        else
                        {
                            manualResetEvent.Set();// 恢复正常的代码
                        }
                    });
                }
                if (manualResetEvent.WaitOne())
                {
                    Console.WriteLine("没有死锁");
                }
    
                // 正常的执行是肯定先执行下面这一句
                Console.WriteLine("等着QueueUserWorkItem完成后才执行");

    五.线程池回调(不带返回值)

            private void ThreadPoolWithCallback(Action act, Action callback) {
                ThreadPool.QueueUserWorkItem( t => {
                    act.Invoke();
                    Thread.Sleep(2000);
                    callback.Invoke();
                });
            } 
    
    // 使用的时候
     // 没有返回参数
                ThreadWithCallback(() =>
                {
                    Console.WriteLine("这里是Action:" + Thread.CurrentThread.ManagedThreadId.ToString());
                }, () =>
                {
                    Console.WriteLine("这里是CallBack:" + Thread.CurrentThread.ManagedThreadId.ToString());
                });

    六.线程回调(带返回值)

    private Func<T> ThreadWithReturn<T>(Func<T> func) {
                T t = default(T);
                Thread thread = new Thread(() =>
                {
                     t = func.Invoke();
                });
                thread.Start();
    
                // 返回一个委托函数
                // 委托函数里面还有一个return,这是属于另一个函数了
                // 在返回这个Func的时候是不会卡界面的
                return () =>
                {
                    while (thread.ThreadState != ThreadState.Stopped)
                    {
                        Console.WriteLine("我的");
                        Thread.Sleep(2000);
                    }
                    // 也可以
                    //thread.Join();// 表示线程执行到这里后就等待
                    return t;
                };
            }
    
    // 使用的时候
     Func<int> func = ThreadWithReturn<int>(() => {
                    Thread.Sleep(2000);
                    return DateTime.Now.Millisecond;
                });

    七.线程池的优点

    1)降低资源消耗,尽最大可能的避免线程的创建和销毁带来的性能开销。

    2)  提高响应速度,当任务来时可以直接使用,不用等待线程创建(在线程池的线程未被全部占用的时候,可以直接进行运算)

    3)避免大量的线程间因互相抢占系统资源导致的阻塞现象。(线程池会自动管理线程)

    4}提高线程的可管理性。(线程池会自动管理线程)

    更多相关内容
  • } ThreadPool.QueueUserWorkItem(new WaitCallback(Process), new Demo { dtloop = dtloop, linedata = linedata, username = username, stafflist = stafflist, tasklogList = tasklogList, clrloaddetail = ...

    示例,将数据分批 ,每次1000条放入线程池中执行 dt 是查询出来的DataTable 数据。

        public List<AtmTaskLogdetail> OrderKPI_New(DateTime timeTo)
        {
    			    List<AtmTaskLogdetail> tasklog = new List<AtmTaskLogdetail>();
                    int calcmaxorder = 1000;
                    int ordercounthas = dt.Rows.Count;
                    int hasloop = ordercounthas / calcmaxorder;
                    if (ordercounthas % calcmaxorder > 0)
                    {
                        hasloop = hasloop + 1;
                    }
                    showLog("总订单数:" + ordercounthas, "构成表的数量:" + hasloop);
    
                    Threadtasklog = new List<AtmTaskLogdetail>();
                    for (int i = 1; i <= hasloop; i++)
                    {
                        DataTable dtloop = dt.Clone();
                        int start = i * calcmaxorder - calcmaxorder;
                        int end = i * calcmaxorder;
                        for (int z = start; z < end; z++)
                        {
                            if (z >= ordercounthas) break;
                            dtloop.Rows.Add(dt.Rows[z].ItemArray);
                        }
    
    
                        ThreadPool.QueueUserWorkItem(new WaitCallback(Process), new Demo { dtloop = dtloop, linedata = linedata, username = username, stafflist = stafflist, tasklogList = tasklogList, clrloaddetail = clrloaddetail, countdetail = countdetail, clrccttotalpreloadList = clrccttotalpreloadList, clrtotalcctcountList = clrtotalcctcountList, pdatotalclrList = pdatotalclrList, inventoryinoutitemlist = inventoryinoutitemlist, listbox = listbox, receivebox = receivebox, task = task, clrtotalretailpreloadList = clrtotalretailpreloadList, ccttotalloaddetailList = ccttotalloaddetailList, retailloaddetailList = retailloaddetailList, logislist = logislist, linegooddt = linegooddt, clrtotalretailcountList = clrtotalretailcountList, pdaload = pdaload, tasktruckbind = tasktruckbind });
    
    
                     //   showLog("执行订单数量:", "总数:" + dtloop.Rows.Count);
                    }
                    #endregion
    
                    while (!(ordercounthas == Threadtasklog.Count))
                    {
                        Thread.Sleep(50);
                    }
                    tasklog.AddRange(Threadtasklog);
    
                    return tasklog;
          }
    
    
    
    
    
    
    
     private class Demo
        {
            public DataTable dtloop { get; set; }
            public List<LineData> linedata { get; set; }
            public DataTable username { get; set; }
            public List<StaffWork> stafflist { get; set; }
            public List<tmplogs> tasklogList { get; set; }
            public DataTable clrloaddetail { get; set; }
            public DataTable countdetail { get; set; }
            public DataTable clrccttotalpreloadList { get; set; }
            public DataTable clrtotalcctcountList { get; set; }
            public DataTable pdatotalclrList { get; set; }
            public DataTable inventoryinoutitemlist { get; set; }
            public DataTable listbox { get; set; }
            public DataTable receivebox { get; set; }
            public DataTable task { get; set; }
            public DataTable clrtotalretailpreloadList { get; set; }
            public DataTable ccttotalloaddetailList { get; set; }
            public DataTable retailloaddetailList { get; set; }
            public DataTable logislist { get; set; }
            public DataTable tasktruckbind { get; set; }
            public DataTable linegooddt { get; set; }
            public DataTable clrtotalretailcountList { get; set; }
            public List<tmppdaload> pdaload { get; set; }
    
        }
    
    
    
    
    
        static List<AtmTaskLogdetail> Threadtasklog = new List<AtmTaskLogdetail>();
        private static void Process(object DemoList)
        {
                Demo List = DemoList as Demo;
                DataTable dtloop = List.dtloop;
                List<LineData> linedata = List.linedata;
                DataTable username = List.username;
                List<StaffWork> stafflist = List.stafflist;
                List<tmplogs> tasklogList = List.tasklogList;
                DataTable clrloaddetail = List.clrloaddetail;
                DataTable countdetail = List.countdetail;
                DataTable clrccttotalpreloadList = List.clrccttotalpreloadList;
                DataTable clrtotalcctcountList = List.clrtotalcctcountList;
                DataTable pdatotalclrList = List.pdatotalclrList;
                DataTable inventoryinoutitemlist = List.inventoryinoutitemlist;
                DataTable listbox = List.listbox;
                DataTable receivebox = List.receivebox;
                DataTable task = List.task;
                DataTable clrtotalretailpreloadList = List.clrtotalretailpreloadList;
                DataTable ccttotalloaddetailList = List.ccttotalloaddetailList;
                DataTable retailloaddetailList = List.retailloaddetailList;
                DataTable logislist = List.logislist;
                DataTable tasktruckbind = List.tasktruckbind;
                DataTable linegooddt = List.linegooddt;
                DataTable clrtotalretailcountList = List.clrtotalretailcountList;
                List<tmppdaload> pdaload = List.pdaload;
    
    
    
                    AtmTaskLogdetail log = new AtmTaskLogdetail();
                    log.TaskDetailId = item["orderid"].ToStr();
    
    
    			    lock (Threadtasklog)
                    {
                        Threadtasklog.Add(log);
                    }
       	}                
    
    展开全文
  • C# Threadpool线程池

    2020-08-22 09:20:20
    若想测试线程池中有多少线程正在投入使用,可以通过ThreadPool.GetAvailableThreads(out in workThreads,out int conoletionPortThreads)方法。 方法 说明 GetAvailableThreads 剩余空闲线程数 GetMaxThreads 最多...

    CLR线程池并不会在CLR初始化时立即建立线程,而是在应用程序要创建线程来运行任务时,线程池才初始化一个线程。
    线程池初始化时是没有线程的,线程池里的线程的初始化与其他线程一样,但是在完成任务以后,该线程不会自行销毁,而是以挂起的状态返回到线程池。直到应用程序再次向线程池发出请求时,线程池里挂起的线程就会再度激活执行任务。
    这样既节省了建立线程所造成的性能损耗,也可以让多个任务反复重用同一线程,从而在应用程序生存期内节约大量开销。

    通过CLR线程池所建立的线程总是默认为后台线程,优先级数为ThreadPriority.Normal。

    CLR线程池分为工作者线程(workerThreads)与I/O线程(completionPortThreads)两种:

    工作者线程是主要用作管理CLR内部对象的运作,通常用于计算密集的任务。
    I/O(Input/Output)线程主要用于与外部系统交互信息,如输入输出,CPU仅需在任务开始的时候,将任务的参数传递给设备,然后启动硬件设备即可。等任务完成的时候,CPU收到一个通知,一般来说是一个硬件的中断信号,此时CPU继续后继的处理工作。在处理过程中,CPU是不必完全参与处理过程的,如果正在运行的线程不交出CPU的控制权,那么线程也只能处于等待状态,即使操作系统将当前的CPU调度给其他线程,此时线程所占用的空间还是被占用,而并没有CPU处理这个线程,可能出现线程资源浪费的问题。如果这是一个网络服务程序,每一个网络连接都使用一个线程管理,可能出现大量线程都在等待网络通信,随着网络连接的不断增加,处于等待状态的线程将会很消耗尽所有的内存资源。可以考虑使用线程池解决这个问题。
      线程池的最大值一般默认为1000、2000。当大于此数目的请求时,将保持排队状态,直到线程池里有线程可用。

      使用CLR线程池的工作者线程一般有两种方式:

    通过ThreadPool.QueueUserWorkItem()方法;
    通过委托;
      要注意,不论是通过ThreadPool.QueueUserWorkItem()还是委托,调用的都是线程池里的线程。

    通过以下两个方法可以读取和设置CLR线程池中工作者线程与I/O线程的最大线程数。

    ThreadPool.GetMax(out in workerThreads,out int completionPortThreads);
    ThreadPool.SetMax(int workerThreads,int completionPortThreads);
      若想测试线程池中有多少线程正在投入使用,可以通过ThreadPool.GetAvailableThreads(out in workThreads,out int conoletionPortThreads)方法。

    方法    说明
    GetAvailableThreads    剩余空闲线程数
    GetMaxThreads    最多可用线程数,所有大于此数目的请求将保持排队状态,直到线程池线程变为可用
    GetMinThreads    检索线程池在新请求预测中维护的空闲线程数
    QueueUserWorkItem    启动线程池里得一个线程(队列的方式,如线程池暂时没空闲线程,则进入队列排队)
    SetMaxThreads    设置线程池中的最大线程数
    SetMinThreads    设置线程池最少需要保留的线程数
    我们可以使用线程池来解决上面的大部分问题,跟使用单个线程相比,使用线程池有如下优点:

    1、缩短应用程序的响应时间。因为在线程池中有线程的线程处于等待分配任务状态(只要没有超过线程池的最大上限),无需创建线程。

    2、不必管理和维护生存周期短暂的线程,不用在创建时为其分配资源,在其执行完任务之后释放资源。

    3、线程池会根据当前系统特点对池内的线程进行优化处理。

    总之使用线程池的作用就是减少创建和销毁线程的系统开销。在.NET中有一个线程的类ThreadPool,它提供了线程池的管理。

    ThreadPool是一个静态类,它没有构造函数,对外提供的函数也全部是静态的。其中有一个QueueUserWorkItem方法,它有两种重载形式,如下:

    public static bool QueueUserWorkItem(WaitCallback callBack):将方法排入队列以便执行。此方法在有线程池线程变得可用时执行。

    public static bool QueueUserWorkItem(WaitCallback callBack,Object state):将方法排入队列以便执行,并指定包含该方法所用数据的对象。此方法在有线程池线程变得可用时执行。

    QueueUserWorkItem方法中使用的的WaitCallback参数表示一个delegate,它的声明如下:

    public delegate void WaitCallback(Object state)

    如果需要传递任务信息可以利用WaitCallback中的state参数,类似于ParameterizedThreadStart委托。

    下面是一个ThreadPool的例子,代码如下:

    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Threading;

    namespace ConsoleApp1
    {
        class ThreadPoolDemo
        {
            public ThreadPoolDemo()
            {
            }

            public void Work()
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(CountProcess));
                ThreadPool.QueueUserWorkItem(new WaitCallback(GetEnvironmentVariables));
            }
            /// <summary>  
            /// 统计当前正在运行的系统进程信息  
            /// </summary>  
            /// <param name="state"></param>  
            private void CountProcess(object state)
            {
                Process[] processes = Process.GetProcesses();
                foreach (Process p in processes)
                {
                    try
                    {
                        Console.WriteLine("进程信息:Id:{0},ProcessName:{1},StartTime:{2}", p.Id, p.ProcessName, p.StartTime);
                    }
                    catch (Win32Exception e)
                    {
                        Console.WriteLine("ProcessName:{0}", p.ProcessName);
                    }
                    finally
                    {
                    }
                }
                Console.WriteLine("获取进程信息完毕。");
            }
            /// <summary>  
            /// 获取当前机器系统变量设置  
            /// </summary>  
            /// <param name="state"></param>  
            public void GetEnvironmentVariables(object state)
            {
                IDictionary list = System.Environment.GetEnvironmentVariables();
                foreach (DictionaryEntry item in list)
                {
                    Console.WriteLine("系统变量信息:key={0},value={1}", item.Key, item.Value);
                }
                Console.WriteLine("获取系统变量信息完毕。");
            }
        }
    }

    using System;
    using System.Threading;

    namespace ConsoleApp1
    {

        class Program
        {
            static void Main(string[] args)
            {
                ThreadPoolDemo tpd1 = new ThreadPoolDemo();
                tpd1.Work();
                Thread.Sleep(5000);
                Console.WriteLine("OK");
                Console.ReadLine();
            }
        }
    }

     

    利用ThreadPool调用工作线程和IO线程的范例

    using System;
    using System.Collections;
    using System.IO;
    using System.Text;
    using System.Threading;

    namespace ConsoleApp1
    {

        class Program
        {
            static void Main(string[] args)
            {
                // 设置线程池中处于活动的线程的最大数目
                // 设置线程池中工作者线程数量为1000,I/O线程数量为1000
                ThreadPool.SetMaxThreads(1000, 1000);
                Console.WriteLine("Main Thread: queue an asynchronous method");
                PrintMessage("Main Thread Start");

                // 把工作项添加到队列中,此时线程池会用工作者线程去执行回调方法            
                ThreadPool.QueueUserWorkItem(asyncMethod);
                asyncWriteFile();
                Console.Read();
            }

            // 方法必须匹配WaitCallback委托
            private static void asyncMethod(object state)
            {
                Thread.Sleep(1000);
                PrintMessage("Asynchoronous Method");
                Console.WriteLine("Asynchoronous thread has worked ");
            }


            #region 异步读取文件模块
            private static void asyncReadFile()
            {
                byte[] byteData = new byte[1024];
                FileStream stream = new FileStream(@"D:\123.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 1024, true);
                //把FileStream对象,byte[]对象,长度等有关数据绑定到FileDate对象中,以附带属性方式送到回调函数
                Hashtable ht = new Hashtable();
                ht.Add("Length", (int)stream.Length);
                ht.Add("Stream", stream);
                ht.Add("ByteData", byteData);

                //启动异步读取,倒数第二个参数是指定回调函数,倒数第一个参数是传入回调函数中的参数
                stream.BeginRead(byteData, 0, (int)ht["Length"], new AsyncCallback(Completed), ht);
                PrintMessage("asyncReadFile Method");
            }

            //实际参数就是回调函数
            static void Completed(IAsyncResult result)
            {
                Thread.Sleep(2000);
                PrintMessage("asyncReadFile Completed Method");
                //参数result实际上就是Hashtable对象,以FileStream.EndRead完成异步读取
                Hashtable ht = (Hashtable)result.AsyncState;
                FileStream stream = (FileStream)ht["Stream"];
                int length = stream.EndRead(result);
                stream.Close();
                string str = Encoding.UTF8.GetString(ht["ByteData"] as byte[]);
                Console.WriteLine(str);
                stream.Close();
            }
            #endregion

            #region 异步写入文件模块
            //异步写入模块
            private static void asyncWriteFile()
            {
                //文件名 文件创建方式 文件权限 文件进程共享 缓冲区大小为1024 是否启动异步I/O线程为true
                FileStream stream = new FileStream(@"D:\123.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 1024, true);
                //这里要注意,如果写入的字符串很小,则.Net会使用辅助线程写,因为这样比较快
                byte[] bytes = Encoding.UTF8.GetBytes("你在他乡还好吗?");
                //异步写入开始,倒数第二个参数指定回调函数,最后一个参数将自身传到回调函数里,用于结束异步线程
                stream.BeginWrite(bytes, 0, (int)bytes.Length, new AsyncCallback(Callback), stream);
                PrintMessage("AsyncWriteFile Method");
            }

            static void Callback(IAsyncResult result)
            {
                //显示线程池现状
                Thread.Sleep(2000);
                PrintMessage("AsyncWriteFile Callback Method");
                //通过result.AsyncState再强制转换为FileStream就能够获取FileStream对象,用于结束异步写入
                FileStream stream = (FileStream)result.AsyncState;
                stream.EndWrite(result);
                stream.Flush();
                stream.Close();
                asyncReadFile();
            }
            #endregion

            // 打印线程池信息
            private static void PrintMessage(String data)
            {
                int workthreadnumber;
                int iothreadnumber;

                // 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
                // 获得的可用I/O线程数量给iothreadnumber变量
                ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);

                Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
                    data,
                    Thread.CurrentThread.ManagedThreadId,
                    Thread.CurrentThread.IsBackground.ToString(),
                    workthreadnumber.ToString(),
                    iothreadnumber.ToString());
            }
        }
    }

     

    线程池中放入异步操作

    using System;
    using System.Threading;

    namespace ConsoleApp1
    {

        class Program
        {
            private static void AsyncOperation(object state)
            {
                Console.WriteLine("Operation state: {0}", state ?? "(null)");
                Console.WriteLine("Worker thread id: {0}", Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(TimeSpan.FromSeconds(2));
            }

            static void Main(string[] args)
            {
                const int x = 1;
                const int y = 2;
                const string lambdaState = "lambda state 2";

                ThreadPool.QueueUserWorkItem(AsyncOperation);
                Thread.Sleep(TimeSpan.FromSeconds(1));

                ThreadPool.QueueUserWorkItem(AsyncOperation, "async state");
                Thread.Sleep(TimeSpan.FromSeconds(1));

                ThreadPool.QueueUserWorkItem(state => {
                    Console.WriteLine("Operation state: {0}", state);
                    Console.WriteLine("Worker thread id: {0}", Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(TimeSpan.FromSeconds(2));
                }, "lambda state");

                ThreadPool.QueueUserWorkItem(_ =>
                {
                    Console.WriteLine("Operation state: {0}, {1}", x + y, lambdaState);
                    Console.WriteLine("Worker thread id: {0}", Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(TimeSpan.FromSeconds(2));
                }, "lambda state");

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

     

    线程池同步操作

    using System;
    using System.Threading;

    namespace ConsoleApp1
    {
        class ThreadPoolDemo
        {
            static object lockobj = new object();
            static int Count = 0;
            ManualResetEvent manualEvent;
            public ThreadPoolDemo(ManualResetEvent manualEvent)
            {
                this.manualEvent = manualEvent;
            }
            public void DisplayNumber(object a)
            {

                lock (lockobj)
                {
                    Count++;
                    Console.WriteLine("当前运算结果:{0},Count={1},当前子线程id:{2} 的状态:{3}", a, Count, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState);
                }
                //Console.WriteLine("当前运算结果:{0}", a);
                //Console.WriteLine("当前运算结果:{0},当前子线程id:{1} 的状态:{2}", a,Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState);
                //这里是方法执行时间的模拟,如果注释该行代码,就能看出线程池的功能了
                Thread.Sleep(2000);
                //Console.WriteLine("当前运算结果:{0},Count={1},当前子线程id:{2} 的状态:{3}", a, Count, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState);
                //这里是释放共享锁,让其他线程进入
                manualEvent.Set();


            }
        }
    }

    using System;
    using System.Diagnostics;
    using System.Threading;

    namespace ConsoleApp1
    {

        class Program
        {
            //设定任务数量 
            static int count = 10;
            static void Main(string[] args)
            {
                //让线程池执行5个任务所以也为每个任务加上这个对象保持同步
                ManualResetEvent[] events = new ManualResetEvent[count];
                Console.WriteLine("当前主线程id:{0}", Thread.CurrentThread.ManagedThreadId);

                Stopwatch sw = new Stopwatch();
                sw.Start();
                NoThreadPool(count);
                sw.Stop();
                Console.WriteLine("Execution time using threads: {0}", sw.ElapsedMilliseconds);


                sw.Reset();
                sw.Start();
                //循环每个任务
                for (int i = 0; i < count; i++)
                {
                    //实例化同步工具
                    events[i] = new ManualResetEvent(false);
                    //Test在这里就是任务类,将同步工具的引用传入能保证共享区内每次只有一个线程进入
                    ThreadPoolDemo tst = new ThreadPoolDemo(events[i]);
                    //Thread.Sleep(200);
                    //将任务放入线程池中,让线程池中的线程执行该任务                 
                    ThreadPool.QueueUserWorkItem(tst.DisplayNumber, i);
                }
                //注意这里,设定WaitAll是为了阻塞调用线程(主线程),让其余线程先执行完毕,
                //其中每个任务完成后调用其set()方法(收到信号),当所有
                //的任务都收到信号后,执行完毕,将控制权再次交回调用线程(这里的主线程)
                ManualResetEvent.WaitAll(events);
                sw.Stop();
                Console.WriteLine("Execution time using threads: {0}", sw.ElapsedMilliseconds);
                //Console.WriteLine("所有任务做完!");
                Console.ReadKey();
            }

            static void NoThreadPool(int count)
            {
                for (int i = 0; i < count; i++)
                {
                    Thread.Sleep(2000);
                    Console.WriteLine("当前运算结果:{0},Count={1},当前子线程id:{2} 的状态:{3}", i, i + 1, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState);
                }
            }

        }
    }

     

    线程池中的取消操作

    using System;
    using System.Threading;

    namespace ConsoleApp1
    {

        class Program
        {
            static void Main(string[] args)
            {
                ThreadPool.SetMaxThreads(1000, 1000);
                Console.WriteLine("Main thread run");
                PrintMessage("Start");
                Run();
                Console.ReadKey();
            }

            private static void Run()
            {
                CancellationTokenSource cts = new CancellationTokenSource();

                // 这里用Lambda表达式的方式和使用委托的效果一样的,只是用了Lambda后可以少定义一个方法。
                // 这在这里就是让大家明白怎么lambda表达式如何由委托转变的
                ThreadPool.QueueUserWorkItem(o => Count(cts.Token, 1000));
                ThreadPool.QueueUserWorkItem(callback, cts.Token);

                Console.WriteLine("Press Enter key to cancel the operation\n");
                Console.ReadLine();

                // 传达取消请求            
                cts.Cancel();
                Console.ReadLine();
            }

            private static void callback(object state)
            {
                Thread.Sleep(1000);
                PrintMessage("Asynchoronous Method Start");
                CancellationToken token = (CancellationToken)state;
                Count(token, 1000);
            }

            // 执行的操作,当受到取消请求时停止数数
            private static void Count(CancellationToken token, int countto)
            {
                for (int i = 0; i < countto; i++)
                {
                    if (token.IsCancellationRequested)
                    {
                        Console.WriteLine("Count is canceled");
                        break;
                    }

                    Console.WriteLine(i);
                    Thread.Sleep(300);
                }

                Console.WriteLine("Cout has done");
            }

            // 打印线程池信息
            private static void PrintMessage(String data)
            {
                int workthreadnumber;
                int iothreadnumber;

                // 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
                // 获得的可用I/O线程数量给iothreadnumber变量
                ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);

                Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
                    data,
                    Thread.CurrentThread.ManagedThreadId,
                    Thread.CurrentThread.IsBackground.ToString(),
                    workthreadnumber.ToString(),
                    iothreadnumber.ToString());
            }
        }
    }

     

    Thread与ThreadPool的一个性能比较

    using System;
    using System.Diagnostics;
    using System.Threading;

    namespace ConsoleApp1
    {
        class Program
        {
            static void Main(string[] args)
            {
                const int numberOfOperations = 300;
                var sw = new Stopwatch();
                sw.Start();
                UseThreads(numberOfOperations);
                sw.Stop();
                Console.WriteLine("Execution time using threads: {0}", sw.ElapsedMilliseconds);

                sw.Reset();
                sw.Start();
                UseThreadPool(numberOfOperations);
                sw.Stop();
                Console.WriteLine("Execution time using threadPool: {0}", sw.ElapsedMilliseconds);
            }

            static void UseThreads(int numberOfOperations)
            {
                using (var countdown = new CountdownEvent(numberOfOperations))
                {
                    Console.WriteLine("Scheduling work by creating threads");
                    for (int i = 0; i < numberOfOperations; i++)
                    {
                        var thread = new Thread(() => {
                            Console.Write("{0},", Thread.CurrentThread.ManagedThreadId);
                            Thread.Sleep(TimeSpan.FromSeconds(0.1));
                            countdown.Signal();
                        });
                        thread.Start();
                    }
                    countdown.Wait();
                    Console.WriteLine();
                }
            }

            static void UseThreadPool(int numberOfOperations)
            {
                using (var countdown = new CountdownEvent(numberOfOperations))
                {
                    Console.WriteLine("Starting work on a threadpool");
                    for (int i = 0; i < numberOfOperations; i++)
                    {
                        ThreadPool.QueueUserWorkItem(_ => {
                            Console.Write("{0},", Thread.CurrentThread.ManagedThreadId);
                            Thread.Sleep(TimeSpan.FromSeconds(0.1));
                            countdown.Signal();
                        });
                    }
                    countdown.Wait();
                    Console.WriteLine();
                }
            }
        }
    }

    展开全文
  • C# ThreadPool线程池

    2020-09-07 09:42:35
    若想测试线程池中有多少线程正在投入使用,可以通过ThreadPool.GetAvailableThreads(out in workThreads,out int conoletionPortThreads)方法。 方法 说明 GetAvailableThreads 剩余空闲线程数 GetMaxThreads 最多...

    CLR线程池并不会在CLR初始化时立即建立线程,而是在应用程序要创建线程来运行任务时,线程池才初始化一个线程。
    线程池初始化时是没有线程的,线程池里的线程的初始化与其他线程一样,但是在完成任务以后,该线程不会自行销毁,而是以挂起的状态返回到线程池。直到应用程序再次向线程池发出请求时,线程池里挂起的线程就会再度激活执行任务。
    这样既节省了建立线程所造成的性能损耗,也可以让多个任务反复重用同一线程,从而在应用程序生存期内节约大量开销。

    通过CLR线程池所建立的线程总是默认为后台线程,优先级数为ThreadPriority.Normal。

    CLR线程池分为工作者线程(workerThreads)与I/O线程(completionPortThreads)两种:

    工作者线程是主要用作管理CLR内部对象的运作,通常用于计算密集的任务。
    I/O(Input/Output)线程主要用于与外部系统交互信息,如输入输出,CPU仅需在任务开始的时候,将任务的参数传递给设备,然后启动硬件设备即可。等任务完成的时候,CPU收到一个通知,一般来说是一个硬件的中断信号,此时CPU继续后继的处理工作。在处理过程中,CPU是不必完全参与处理过程的,如果正在运行的线程不交出CPU的控制权,那么线程也只能处于等待状态,即使操作系统将当前的CPU调度给其他线程,此时线程所占用的空间还是被占用,而并没有CPU处理这个线程,可能出现线程资源浪费的问题。如果这是一个网络服务程序,每一个网络连接都使用一个线程管理,可能出现大量线程都在等待网络通信,随着网络连接的不断增加,处于等待状态的线程将会很消耗尽所有的内存资源。可以考虑使用线程池解决这个问题。
      线程池的最大值一般默认为1000、2000。当大于此数目的请求时,将保持排队状态,直到线程池里有线程可用。

      使用CLR线程池的工作者线程一般有两种方式:

    通过ThreadPool.QueueUserWorkItem()方法;
    通过委托;
      要注意,不论是通过ThreadPool.QueueUserWorkItem()还是委托,调用的都是线程池里的线程。

    通过以下两个方法可以读取和设置CLR线程池中工作者线程与I/O线程的最大线程数。

    ThreadPool.GetMax(out in workerThreads,out int completionPortThreads);
    ThreadPool.SetMax(int workerThreads,int completionPortThreads);
      若想测试线程池中有多少线程正在投入使用,可以通过ThreadPool.GetAvailableThreads(out in workThreads,out int conoletionPortThreads)方法。

    方法    说明
    GetAvailableThreads    剩余空闲线程数
    GetMaxThreads    最多可用线程数,所有大于此数目的请求将保持排队状态,直到线程池线程变为可用
    GetMinThreads    检索线程池在新请求预测中维护的空闲线程数
    QueueUserWorkItem    启动线程池里得一个线程(队列的方式,如线程池暂时没空闲线程,则进入队列排队)
    SetMaxThreads    设置线程池中的最大线程数
    SetMinThreads    设置线程池最少需要保留的线程数
    我们可以使用线程池来解决上面的大部分问题,跟使用单个线程相比,使用线程池有如下优点:

    1、缩短应用程序的响应时间。因为在线程池中有线程的线程处于等待分配任务状态(只要没有超过线程池的最大上限),无需创建线程。

    2、不必管理和维护生存周期短暂的线程,不用在创建时为其分配资源,在其执行完任务之后释放资源。

    3、线程池会根据当前系统特点对池内的线程进行优化处理。

    总之使用线程池的作用就是减少创建和销毁线程的系统开销。在.NET中有一个线程的类ThreadPool,它提供了线程池的管理。

    ThreadPool是一个静态类,它没有构造函数,对外提供的函数也全部是静态的。其中有一个QueueUserWorkItem方法,它有两种重载形式,如下:

    public static bool QueueUserWorkItem(WaitCallback callBack):将方法排入队列以便执行。此方法在有线程池线程变得可用时执行。

    public static bool QueueUserWorkItem(WaitCallback callBack,Object state):将方法排入队列以便执行,并指定包含该方法所用数据的对象。此方法在有线程池线程变得可用时执行。

    QueueUserWorkItem方法中使用的的WaitCallback参数表示一个delegate,它的声明如下:

    public delegate void WaitCallback(Object state)

    如果需要传递任务信息可以利用WaitCallback中的state参数,类似于ParameterizedThreadStart委托。

    下面是一个ThreadPool的例子,代码如下:

    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Threading;

    namespace ConsoleApp1
    {
        class ThreadPoolDemo
        {
            public ThreadPoolDemo()
            {
            }

            public void Work()
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(CountProcess));
                ThreadPool.QueueUserWorkItem(new WaitCallback(GetEnvironmentVariables));
            }
            /// <summary>  
            /// 统计当前正在运行的系统进程信息  
            /// </summary>  
            /// <param name="state"></param>  
            private void CountProcess(object state)
            {
                Process[] processes = Process.GetProcesses();
                foreach (Process p in processes)
                {
                    try
                    {
                        Console.WriteLine("进程信息:Id:{0},ProcessName:{1},StartTime:{2}", p.Id, p.ProcessName, p.StartTime);
                    }
                    catch (Win32Exception e)
                    {
                        Console.WriteLine("ProcessName:{0}", p.ProcessName);
                    }
                    finally
                    {
                    }
                }
                Console.WriteLine("获取进程信息完毕。");
            }
            /// <summary>  
            /// 获取当前机器系统变量设置  
            /// </summary>  
            /// <param name="state"></param>  
            public void GetEnvironmentVariables(object state)
            {
                IDictionary list = System.Environment.GetEnvironmentVariables();
                foreach (DictionaryEntry item in list)
                {
                    Console.WriteLine("系统变量信息:key={0},value={1}", item.Key, item.Value);
                }
                Console.WriteLine("获取系统变量信息完毕。");
            }
        }
    }

    using System;
    using System.Threading;

    namespace ConsoleApp1
    {

        class Program
        {
            static void Main(string[] args)
            {
                ThreadPoolDemo tpd1 = new ThreadPoolDemo();
                tpd1.Work();
                Thread.Sleep(5000);
                Console.WriteLine("OK");
                Console.ReadLine();
            }
        }
    }

     

    利用ThreadPool调用工作线程和IO线程的范例

    using System;
    using System.Collections;
    using System.IO;
    using System.Text;
    using System.Threading;

    namespace ConsoleApp1
    {

        class Program
        {
            static void Main(string[] args)
            {
                // 设置线程池中处于活动的线程的最大数目
                // 设置线程池中工作者线程数量为1000,I/O线程数量为1000
                ThreadPool.SetMaxThreads(1000, 1000);
                Console.WriteLine("Main Thread: queue an asynchronous method");
                PrintMessage("Main Thread Start");

                // 把工作项添加到队列中,此时线程池会用工作者线程去执行回调方法            
                ThreadPool.QueueUserWorkItem(asyncMethod);
                asyncWriteFile();
                Console.Read();
            }

            // 方法必须匹配WaitCallback委托
            private static void asyncMethod(object state)
            {
                Thread.Sleep(1000);
                PrintMessage("Asynchoronous Method");
                Console.WriteLine("Asynchoronous thread has worked ");
            }


            #region 异步读取文件模块
            private static void asyncReadFile()
            {
                byte[] byteData = new byte[1024];
                FileStream stream = new FileStream(@"D:\123.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 1024, true);
                //把FileStream对象,byte[]对象,长度等有关数据绑定到FileDate对象中,以附带属性方式送到回调函数
                Hashtable ht = new Hashtable();
                ht.Add("Length", (int)stream.Length);
                ht.Add("Stream", stream);
                ht.Add("ByteData", byteData);

                //启动异步读取,倒数第二个参数是指定回调函数,倒数第一个参数是传入回调函数中的参数
                stream.BeginRead(byteData, 0, (int)ht["Length"], new AsyncCallback(Completed), ht);
                PrintMessage("asyncReadFile Method");
            }

            //实际参数就是回调函数
            static void Completed(IAsyncResult result)
            {
                Thread.Sleep(2000);
                PrintMessage("asyncReadFile Completed Method");
                //参数result实际上就是Hashtable对象,以FileStream.EndRead完成异步读取
                Hashtable ht = (Hashtable)result.AsyncState;
                FileStream stream = (FileStream)ht["Stream"];
                int length = stream.EndRead(result);
                stream.Close();
                string str = Encoding.UTF8.GetString(ht["ByteData"] as byte[]);
                Console.WriteLine(str);
                stream.Close();
            }
            #endregion

            #region 异步写入文件模块
            //异步写入模块
            private static void asyncWriteFile()
            {
                //文件名 文件创建方式 文件权限 文件进程共享 缓冲区大小为1024 是否启动异步I/O线程为true
                FileStream stream = new FileStream(@"D:\123.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, 1024, true);
                //这里要注意,如果写入的字符串很小,则.Net会使用辅助线程写,因为这样比较快
                byte[] bytes = Encoding.UTF8.GetBytes("你在他乡还好吗?");
                //异步写入开始,倒数第二个参数指定回调函数,最后一个参数将自身传到回调函数里,用于结束异步线程
                stream.BeginWrite(bytes, 0, (int)bytes.Length, new AsyncCallback(Callback), stream);
                PrintMessage("AsyncWriteFile Method");
            }

            static void Callback(IAsyncResult result)
            {
                //显示线程池现状
                Thread.Sleep(2000);
                PrintMessage("AsyncWriteFile Callback Method");
                //通过result.AsyncState再强制转换为FileStream就能够获取FileStream对象,用于结束异步写入
                FileStream stream = (FileStream)result.AsyncState;
                stream.EndWrite(result);
                stream.Flush();
                stream.Close();
                asyncReadFile();
            }
            #endregion

            // 打印线程池信息
            private static void PrintMessage(String data)
            {
                int workthreadnumber;
                int iothreadnumber;

                // 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
                // 获得的可用I/O线程数量给iothreadnumber变量
                ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);

                Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
                    data,
                    Thread.CurrentThread.ManagedThreadId,
                    Thread.CurrentThread.IsBackground.ToString(),
                    workthreadnumber.ToString(),
                    iothreadnumber.ToString());
            }
        }
    }

     

    线程池中放入异步操作

    using System;
    using System.Threading;

    namespace ConsoleApp1
    {

        class Program
        {
            private static void AsyncOperation(object state)
            {
                Console.WriteLine("Operation state: {0}", state ?? "(null)");
                Console.WriteLine("Worker thread id: {0}", Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(TimeSpan.FromSeconds(2));
            }

            static void Main(string[] args)
            {
                const int x = 1;
                const int y = 2;
                const string lambdaState = "lambda state 2";

                ThreadPool.QueueUserWorkItem(AsyncOperation);
                Thread.Sleep(TimeSpan.FromSeconds(1));

                ThreadPool.QueueUserWorkItem(AsyncOperation, "async state");
                Thread.Sleep(TimeSpan.FromSeconds(1));

                ThreadPool.QueueUserWorkItem(state => {
                    Console.WriteLine("Operation state: {0}", state);
                    Console.WriteLine("Worker thread id: {0}", Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(TimeSpan.FromSeconds(2));
                }, "lambda state");

                ThreadPool.QueueUserWorkItem(_ =>
                {
                    Console.WriteLine("Operation state: {0}, {1}", x + y, lambdaState);
                    Console.WriteLine("Worker thread id: {0}", Thread.CurrentThread.ManagedThreadId);
                    Thread.Sleep(TimeSpan.FromSeconds(2));
                }, "lambda state");

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

     

    线程池同步操作

    using System;
    using System.Threading;

    namespace ConsoleApp1
    {
        class ThreadPoolDemo
        {
            static object lockobj = new object();
            static int Count = 0;
            ManualResetEvent manualEvent;
            public ThreadPoolDemo(ManualResetEvent manualEvent)
            {
                this.manualEvent = manualEvent;
            }
            public void DisplayNumber(object a)
            {

                lock (lockobj)
                {
                    Count++;
                    Console.WriteLine("当前运算结果:{0},Count={1},当前子线程id:{2} 的状态:{3}", a, Count, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState);
                }
                //Console.WriteLine("当前运算结果:{0}", a);
                //Console.WriteLine("当前运算结果:{0},当前子线程id:{1} 的状态:{2}", a,Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState);
                //这里是方法执行时间的模拟,如果注释该行代码,就能看出线程池的功能了
                Thread.Sleep(2000);
                //Console.WriteLine("当前运算结果:{0},Count={1},当前子线程id:{2} 的状态:{3}", a, Count, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState);
                //这里是释放共享锁,让其他线程进入
                manualEvent.Set();


            }
        }
    }

    using System;
    using System.Diagnostics;
    using System.Threading;

    namespace ConsoleApp1
    {

        class Program
        {
            //设定任务数量 
            static int count = 10;
            static void Main(string[] args)
            {
                //让线程池执行5个任务所以也为每个任务加上这个对象保持同步
                ManualResetEvent[] events = new ManualResetEvent[count];
                Console.WriteLine("当前主线程id:{0}", Thread.CurrentThread.ManagedThreadId);

                Stopwatch sw = new Stopwatch();
                sw.Start();
                NoThreadPool(count);
                sw.Stop();
                Console.WriteLine("Execution time using threads: {0}", sw.ElapsedMilliseconds);


                sw.Reset();
                sw.Start();
                //循环每个任务
                for (int i = 0; i < count; i++)
                {
                    //实例化同步工具
                    events[i] = new ManualResetEvent(false);
                    //Test在这里就是任务类,将同步工具的引用传入能保证共享区内每次只有一个线程进入
                    ThreadPoolDemo tst = new ThreadPoolDemo(events[i]);
                    //Thread.Sleep(200);
                    //将任务放入线程池中,让线程池中的线程执行该任务                 
                    ThreadPool.QueueUserWorkItem(tst.DisplayNumber, i);
                }
                //注意这里,设定WaitAll是为了阻塞调用线程(主线程),让其余线程先执行完毕,
                //其中每个任务完成后调用其set()方法(收到信号),当所有
                //的任务都收到信号后,执行完毕,将控制权再次交回调用线程(这里的主线程)
                ManualResetEvent.WaitAll(events);
                sw.Stop();
                Console.WriteLine("Execution time using threads: {0}", sw.ElapsedMilliseconds);
                //Console.WriteLine("所有任务做完!");
                Console.ReadKey();
            }

            static void NoThreadPool(int count)
            {
                for (int i = 0; i < count; i++)
                {
                    Thread.Sleep(2000);
                    Console.WriteLine("当前运算结果:{0},Count={1},当前子线程id:{2} 的状态:{3}", i, i + 1, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.ThreadState);
                }
            }

        }
    }

     

    线程池中的取消操作

    using System;
    using System.Threading;

    namespace ConsoleApp1
    {

        class Program
        {
            static void Main(string[] args)
            {
                ThreadPool.SetMaxThreads(1000, 1000);
                Console.WriteLine("Main thread run");
                PrintMessage("Start");
                Run();
                Console.ReadKey();
            }

            private static void Run()
            {
                CancellationTokenSource cts = new CancellationTokenSource();

                // 这里用Lambda表达式的方式和使用委托的效果一样的,只是用了Lambda后可以少定义一个方法。
                // 这在这里就是让大家明白怎么lambda表达式如何由委托转变的
                ThreadPool.QueueUserWorkItem(o => Count(cts.Token, 1000));
                ThreadPool.QueueUserWorkItem(callback, cts.Token);

                Console.WriteLine("Press Enter key to cancel the operation\n");
                Console.ReadLine();

                // 传达取消请求            
                cts.Cancel();
                Console.ReadLine();
            }

            private static void callback(object state)
            {
                Thread.Sleep(1000);
                PrintMessage("Asynchoronous Method Start");
                CancellationToken token = (CancellationToken)state;
                Count(token, 1000);
            }

            // 执行的操作,当受到取消请求时停止数数
            private static void Count(CancellationToken token, int countto)
            {
                for (int i = 0; i < countto; i++)
                {
                    if (token.IsCancellationRequested)
                    {
                        Console.WriteLine("Count is canceled");
                        break;
                    }

                    Console.WriteLine(i);
                    Thread.Sleep(300);
                }

                Console.WriteLine("Cout has done");
            }

            // 打印线程池信息
            private static void PrintMessage(String data)
            {
                int workthreadnumber;
                int iothreadnumber;

                // 获得线程池中可用的线程,把获得的可用工作者线程数量赋给workthreadnumber变量
                // 获得的可用I/O线程数量给iothreadnumber变量
                ThreadPool.GetAvailableThreads(out workthreadnumber, out iothreadnumber);

                Console.WriteLine("{0}\n CurrentThreadId is {1}\n CurrentThread is background :{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is: {4}\n",
                    data,
                    Thread.CurrentThread.ManagedThreadId,
                    Thread.CurrentThread.IsBackground.ToString(),
                    workthreadnumber.ToString(),
                    iothreadnumber.ToString());
            }
        }
    }

     

    Thread与ThreadPool的一个性能比较

    using System;
    using System.Diagnostics;
    using System.Threading;

    namespace ConsoleApp1
    {
        class Program
        {
            static void Main(string[] args)
            {
                const int numberOfOperations = 300;
                var sw = new Stopwatch();
                sw.Start();
                UseThreads(numberOfOperations);
                sw.Stop();
                Console.WriteLine("Execution time using threads: {0}", sw.ElapsedMilliseconds);

                sw.Reset();
                sw.Start();
                UseThreadPool(numberOfOperations);
                sw.Stop();
                Console.WriteLine("Execution time using threadPool: {0}", sw.ElapsedMilliseconds);
            }

            static void UseThreads(int numberOfOperations)
            {
                using (var countdown = new CountdownEvent(numberOfOperations))
                {
                    Console.WriteLine("Scheduling work by creating threads");
                    for (int i = 0; i < numberOfOperations; i++)
                    {
                        var thread = new Thread(() => {
                            Console.Write("{0},", Thread.CurrentThread.ManagedThreadId);
                            Thread.Sleep(TimeSpan.FromSeconds(0.1));
                            countdown.Signal();
                        });
                        thread.Start();
                    }
                    countdown.Wait();
                    Console.WriteLine();
                }
            }

            static void UseThreadPool(int numberOfOperations)
            {
                using (var countdown = new CountdownEvent(numberOfOperations))
                {
                    Console.WriteLine("Starting work on a threadpool");
                    for (int i = 0; i < numberOfOperations; i++)
                    {
                        ThreadPool.QueueUserWorkItem(_ => {
                            Console.Write("{0},", Thread.CurrentThread.ManagedThreadId);
                            Thread.Sleep(TimeSpan.FromSeconds(0.1));
                            countdown.Signal();
                        });
                    }
                    countdown.Wait();
                    Console.WriteLine();
                }
            }
        }
    }

    展开全文
  • C# ThreadPool 线程池

    2022-08-07 15:46:32
    代码】C# ThreadPool 线程池。
  • ThreadPool静态类通过QueueUserWorkItem()方法将工作函数排入线程池; 每排入一个工作函数,就相当于请求创建一个线程; 线程池的作用: 1、线程池是为突然大量爆发的线程设计的,通过有限的几个固定线程为大量的...
  • 将文件传输过程放在新线程中使用的是ThreadPool.QueueUserWorkItem()方法,调用方式是: protected void Page_Load(object sender, EventArgs e) { List<string> fileCollection = new List(); fileCollection...
  • C# ThreadPool简单用法

    千次阅读 2018-05-28 16:57:52
     C#中的多线程方式有很多种,其中一个比较简单好用的就是ThreadPool。MSDN中对ThreadPool的描述是:提供一个线程池,该线程池可用于执行任务、发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。 我个人...
  • C#ThreadPool.QueueUserWorkItem实例

    千次阅读 2016-10-25 15:28:02
    如果想要4个函数按顺序执行,一种可以在主线程中等待一段时间在执行下一个,第二中可以通过ThreadPool.SetMaxThreads 和ThreadPoolMinThreads,控制线程池中线程的可执行的线程个数来实现。不知道这样做是否合理。 ...
  • ThreadPool和join.rar,ThreadPool和join,joinDemo.rar,ThreadPoolDemo.rar
  • C# ThreadPool的简单用法

    千次阅读 2016-05-26 17:40:31
    C#中的多线程方式有很多种,其中一个比较简单好用的就是ThreadPool。MSDN中对ThreadPool的描述是:提供一个线程池,该线程池可用于执行任务、发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。 我个人...
  •  System.Threading.ThreadPool.QueueUserWorkItem(new WaitCallback(testMethod), _ManualEvents[i]);  }  WaitHandle.WaitAll(_ManualEvents);  // 线程结束后执行后面的主线程代码   Console.WriteLine(...
  • 前提 ThreadPool 设置了最大并行数量一旦设置了最大并行数,如果有下载及上传任务线程,就不能大于并行数千万不能大于并行数 千万不能大于并行数 千万不能大于并行数PS:我使用的是Http连接。。。原因:一旦超过最大...
  • 利用线程池来ThreadPool.QueueUserWorkItem来处理多线程问题,本人也是初学着,欢迎大家多多来探讨多线程的技术问题..
  • C#ThreadPool与Thread

    2019-10-05 04:33:06
    voidExample() { //连接ProcessFile方法到线程池. //注意:'a'是一个作为参数的对象 ThreadPool.QueueUserWorkItem(newWaitCallback(ProcessFile),a); } privatev...
  • C# ThreadPool类(线程池)

    2018-08-19 23:34:00
     若想测试线程池中有多少线程正在投入使用,可以通过ThreadPool.GetAvailableThreads(out in workThreads,out int conoletionPortThreads)方法。 方法 说明 GetAvailableThreads 剩余空闲线程数 ...
  • 前言:自从task出现后,threadpool地位直线下降,但是一些老的程序员用惯了threadpool,我们在继承开发的时候也会时常看到这个用法,所以我们也很有必要熟悉认识它。什么是线程...
  • C# ThreadPool简单使用

    2018-06-21 10:09:01
     ThreadPool.QueueUserWorkItem(new WaitCallback(processFile), f);//将方法排入队列等待执行,并传入该方法所用参数  }  Console.WriteLine("123");  for (int i = 0; i ; i++)  {  Console.WriteLine("123...
  • C#ThreadPool与Task

    2020-10-22 16:39:33
    1. 线程池(ThreadPool) 为什么要使用线程池? 主要原因是创建一个线程的代价是昂贵的,会消耗较多的系统资源; 线程池原理? 线程池在初始时会自动创建一定数量的线程供程序调用,使用是开发人员不直接分配线程,...
  • C#(ThreadPool)线程池的详解及使用范例

    千次阅读 2021-03-08 16:20:09
    ThreadPool.GetMaxThreads(out maxThreadNum,out portThreadNum); ThreadPool.GetMinThreads(out minThreadNum,out portThreadNum); Console.WriteLine("最大线程数:{0}",maxThreadNum); Console.WriteLine("最小...
  • C# Thread ThreadPool 常用用法总结

    千次阅读 2020-01-09 01:56:03
    本文简单的总结了 C# 中 线程与线程池的常用操作。 开始 Thread 新建控制台应用,并替换Program的代码即可; 示例程序(官方文档示例程序改版): class Program { public static void ThreadProc() { ...
  • 工作线程与I/O线程 在ThreadPool中有这样一个方法: public static bool SetMaxThreads(int workerThreads, int completionPortThreads); 此方法中有两个参数:workerThreads和completionPortThreads。这两...
  • 今天在博客园拜读了 蒋金楠,难道调用ThreadPool.QueueUserWorkItem()的时候,真是必须调用Thread.Sleep(N)吗?自己也深有启发,决定再次陈述个人理解。 我自己差不多写了一段源码,类似蒋金楠那篇博文中的:...
  • C# ThreadPool

    千次阅读 2012-03-12 16:07:01
    这里函数中多了一个 "static",这是因为Main的关系(更大一点就是因为C#语言机制的问题),如果WaitCallback 的对象不是在静态(static)方法中,这个static 是不需要的。 二、接着就是要执行的方法放入线程池中,以便...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,437
精华内容 3,374
关键字:

c#threadpool