zoukankan      html  css  js  c++  java
  • C#线程从陌生到熟悉(3)

    今天我们来谈谈线程池:

    应用程序可以有多个线程,这些线程在休眠状态中需要耗费大量时间来等待事件发生。其他线程可能进入睡眠状态,并且仅定期被唤醒以轮循更改或更新状态信息,然后再次进入休眠状态。为了简化对这些线程的管理,.NET框架为每个进程提供了一个线程池,一个线程池有若干个等待操作状态,当一个等待操作完成时,线程池中的辅助线程会执行回调函数。线程池中的线程由系统管理,程序员不需要费力于线程管理,可以集中精力处理应用程序任务。通过基础类库中的ThreadPool类提供一个线程池,该线程池可用于发送工作现,处理异步I/O,代表其他线程等待及处理计时器.ThreadPool类的所有方法都是静态方法.ThreadPool本身也是一个静态类.
    我们来看看他的定义和一些常用的方法:
     public static class ThreadPool
    {
     [SecuritySafeCritical]
            public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads);
            [SecuritySafeCritical]
            public static void GetMaxThreads(out int workerThreads, out int completionPortThreads);
            [SecuritySafeCritical]
            public static void GetMinThreads(out int workerThreads, out int completionPortThreads);
            [SecuritySafeCritical]
            public static bool QueueUserWorkItem(WaitCallback callBack);
            [SecuritySafeCritical]
            public static bool QueueUserWorkItem(WaitCallback callBack, object state);
    }
    GetAvailableThreads这个方法返回的最大线程池线程数和当前活动线程数之间的差值。 参数 workerThreads: 可用辅助线程的数目。completionPortThreads: 可用异步 I/O 线程的数目。
    GetMaxThreads方法获得当前由线程池维护的辅助线程的最大数目.参数 workerThreads: 线程池中辅助线程的最大数目。completionPortThreads: 当前由线程池维护的空闲异步 I/O 线程的最大数目。
    GetMinThreads方法获得当前由线程池维护的空闲辅助线程的最小数目.参数 workerThreads: 当前由线程池维护的空闲辅助线程的最小数目.completionPortThreads: 当前由线程池维护的空闲异步 I/O 线程的最小数目。
    QueueUserWorkItem方法将方法排入队列以便执行。参数callBack, 表示要执行的方法.state:包含方法所用数据的对象。
    下面看个例子:

     1 using System;
    2 using System.Collections.Generic;
    3 using System.Linq;
    4 using System.Text;
    5 using System.Threading;
    6
    7 namespace ConsoleApplication6
    8 {
    9 class Program
    10 {
    11 static void Main(string[] args)
    12 {
    13 Console.WriteLine("主线程进行异步条用");
    14
    15 AutoResetEvent asyncOpIsDone = new AutoResetEvent(false);
    16 ThreadPool.QueueUserWorkItem(new WaitCallback((x) =>
    17 {
    18
    19 Thread.Sleep(1000);
    20 Console.WriteLine("工作任务");
    21
    22 }));
    23 string s="我的参数";
    24 ThreadPool.QueueUserWorkItem(new WaitCallback((x) =>
    25 {
    26
    27 Thread.Sleep(2000);
    28 Console.WriteLine("工作任务1");
    29 Console.WriteLine(x);
    30
    31 }), s);
    32 ThreadPool.QueueUserWorkItem(new WaitCallback(MyAsyncOperation), asyncOpIsDone);
    33 Console.WriteLine("主线程执行其他");
    34 Console.WriteLine("主线程等待任务处理结束");
    35 asyncOpIsDone.WaitOne();
    36 }
    37 static void MyAsyncOperation(Object state)
    38 {
    39
    40 Thread.Sleep(5000);
    41 Console.WriteLine("工作任务2");
    42 ((AutoResetEvent)state).Set();
    43 }
    44 }
    45 }

     运行的结果为

    这里有个类为AutoResetEvent,他的作用是通知正在等待的线程已发生事件。他是从EventWaitHandle继承而来的!例子中分别用了两种不同的方式调用,第二种是可以传递参数的!工作线程1就传递了"我的参数"字符串!工作线程2运行完了会通知等待的线程已发生事件.这里AutoResetEvent初始化的时候首先将信号设成false,工作线程2如果调用成功,将被设成true. asyncOpIsDone.WaitOne()阻塞当前线程,直到收到信号!

    再看下面的例子

     1 using System;
    2 using System.Collections.Generic;
    3 using System.Linq;
    4 using System.Text;
    5 using System.Threading;
    6
    7 namespace ConsoleApplication7
    8 {
    9 class Program
    10 {
    11 static void Main(string[] args)
    12 {
    13 Console.WriteLine("\n当前线程的HashCode:{0}", Thread.CurrentThread.GetHashCode().ToString());
    14 Console.WriteLine("当前应用域的名字为:{0}", AppDomain.CurrentDomain.FriendlyName);
    15 int workerThreads;
    16 int completionPortThreads;
    17
    18 AutoResetEvent asyncOpIsDone = new AutoResetEvent(false);//信号初始为空
    19 AutoResetEvent asyncOpIsDone2 = new AutoResetEvent(false);
    20 ThreadPool.QueueUserWorkItem(new WaitCallback(MyWork), asyncOpIsDone);
    21 ThreadPool.QueueUserWorkItem(new WaitCallback(MyWork1), asyncOpIsDone2);
    22 ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
    23 Console.WriteLine("得当前由线程池维护的辅助线程的最大数目:{0}", workerThreads);
    24 ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads);
    25 Console.WriteLine("得当前由线程池维护的空闲辅助线程的最小数目:{0}", workerThreads);
    26 /*WaitHandle[] waithandles = new WaitHandle[2];
    27 waithandles[0] = asyncOpIsDone;
    28 waithandles[1] = asyncOpIsDone2;
    29 WaitHandle.WaitAll(waithandles); */
    30 //或者可以这样
    31 asyncOpIsDone.WaitOne();
    32 Console.WriteLine("MyWork结束");
    33 asyncOpIsDone2.WaitOne();
    34 Console.WriteLine("MyWork1结束");
    35 }
    36 static void MyWork(Object state)
    37 {
    38 Console.WriteLine("\n当前线程的HashCode:{0}", Thread.CurrentThread.GetHashCode().ToString());
    39 Console.WriteLine("当前应用域的名字为:{0}", AppDomain.CurrentDomain.FriendlyName);
    40 Thread.Sleep(2000);
    41 ((AutoResetEvent)state).Set();//表示工作已经完成
    42 }
    43 static void MyWork1(Object state)
    44 {
    45 Console.WriteLine("\n当前线程的HashCode:{0}", Thread.CurrentThread.GetHashCode().ToString());
    46 Console.WriteLine("当前应用域的名字为:{0}", AppDomain.CurrentDomain.FriendlyName);
    47 Thread.Sleep(1000);
    48 ((AutoResetEvent)state).Set();//表示工作已经完成
    49 }
    50
    51 }
    52 }

    运行结果为

    本例中可以详细看AutoRestEvent的用法MyWork1实际上先结束的,但是asyncOpIsDone需要等MyWork的信号!所以先输出了MyWork结束.这里还有一个东西我想说的就是WaitHandle,上面的例子已经给出了他的用法!他是AutoRsetEvent的基类.

    还有ThreadPool有一个函数RegisterWaitForSingleObject这个函数还是满有意思的!我这里就不再给出例子了!

    好了,今天就到这了!

  • 相关阅读:
    解决KDE桌面附带文件索引框架Baloo占用资源过多问题
    [Journey with golang] 7. Traps
    [Journey with golang] 6. Reflection
    Codeforces Round #614 (Div. 2)
    [Journey with golang] 5. Concurrent
    2018-2019 9th BSUIR Open Programming Championship
    2019-2020 ACM-ICPC Pacific Northwest Regional Contest
    UFPE Starters Final Try-Outs 2020
    2019 ICPC Asia Taipei Hsinchu Regional Contest
    [Journey with golang] 4. Interface
  • 原文地址:https://www.cnblogs.com/enuo/p/2280009.html
Copyright © 2011-2022 走看看