在多线程的程序中,经常会出现两种情况:

一种情况:   应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应 
                  这一般使用ThreadPool(线程池)来解决;

另一种情况:线程平时都处于休眠状态,只是周期性地被唤醒 
                  这一般使用Timer(定时器)来解决;

本篇文章单单讲线程池[ThreadPool]

ThreadPool类 MSDN帮助信息: http://msdn.microsoft.com/zh-cn/library/system.threading.threadpool.aspx#Y0

将任务添加进线程池:

ThreadPool.QueueUserWorkItem(new WaitCallback(方法名));

重载

ThreadPool.QueueUserWorkItem(new WaitCallback(方法名), 参数);

因为ThreadPool是静态类 所以不需要实例化.

对于线程池主要的控制有控制线程数大小:

ThreadPool.SetMaxThreads 方法

public static bool SetMaxThreads(
int workerThreads,
int completionPortThreads
)

参数:

workerThreads
类型:System.Int32 
线程池中辅助线程的最大数目。
completionPortThreads
类型:System.Int32 
线程池中异步 I/O 线程的最大数目。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace 多线程池试验
{
    class Program
    {
        public static void Main()
        {
            ThreadPool.SetMaxThreads(3, 3);
            for (int i = 0; i < 50; i++)
            {
                thr t = new thr();
                ThreadPool.QueueUserWorkItem(new WaitCallback(t.ThreadProc), i);
            }
            Console.WriteLine("断点测试");
            Thread.Sleep(100000);
 
            Console.WriteLine("运行结束");
        }
 
        public class thr
        {
            public void ThreadProc(object i)
            {
                Console.WriteLine("Thread[" + i.ToString() + "]");
                Thread.Sleep(1000);
            }
        }
    }
}

输出结果:

您会发现 断点测试 在上面了, 这是什么原因呢?

原因:

1. 线程池的启动和终止不是我们程序所能控制的, 我反正是不知道的, 你如果知道的话 可以发邮件给我 henw@163.com

2. 线程池中的线程执行完之后是没有返回值的.

总之一句话, 我们不知道线程池他干了什么, 那么我们该怎么解决 任务完成问题呢?

操作系统提供了一种”信号灯”(ManualResetEvent)

ManualResetEvent 允许线程通过发信号互相通信。通常,此通信涉及一个线程在其他线程进行之前必须完成的任务。当一个线程开始一个活动(此活动必须完成后,其他线程才能开始)时,它调用 Reset 以将 ManualResetEvent 置于非终止状态,此线程可被视为控制 ManualResetEvent。调用 ManualResetEvent 上的 WaitOne 的线程将阻止,并等待信号。当控制线程完成活动时,它调用 Set 以发出等待线程可以继续进行的信号。并释放所有等待线程。一旦它被终止,ManualResetEvent 将保持终止状态(即对 WaitOne 的调用的线程将立即返回,并不阻塞),直到它被手动重置。可以通过将布尔值传递给构造函数来控制 ManualResetEvent 的初始状态,如果初始状态处于终止状态,为 true;否则为 false。

详细见MSDN: http://msdn.microsoft.com/zh-cn/library/system.threading.manualresetevent.aspx

主要使用了

eventX.WaitOne(Timeout.Infinite, true);  阻止当前线程,直到当前 WaitHandle 收到信号为止。

eventX.Set(); 将事件状态设置为终止状态,允许一个或多个等待线程继续。

修改后的程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace 多线程池试验
{
    class Program
    {
        public static void Main()
        {
            //新建ManualResetEvent对象并且初始化为无信号状态
            ManualResetEvent eventX = new ManualResetEvent(false);
            ThreadPool.SetMaxThreads(3, 3);
            thr t = new thr(15, eventX);
            for (int i = 0; i < 15; i++)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(t.ThreadProc), i);
            }
            //等待事件的完成,即线程调用ManualResetEvent.Set()方法
            //eventX.WaitOne  阻止当前线程,直到当前 WaitHandle 收到信号为止。
            eventX.WaitOne(Timeout.Infinite, true);
            Console.WriteLine("断点测试");
            Thread.Sleep(10000);
            Console.WriteLine("运行结束");
        }
 
        public class thr
        {
            public thr(int count,ManualResetEvent mre)
            {
                iMaxCount = count;
                eventX = mre;
            }
 
            public static int iCount = 0;
            public static int iMaxCount = 0;
            public ManualResetEvent eventX;
            public void ThreadProc(object i)
            {
                Console.WriteLine("Thread[" + i.ToString() + "]");
                Thread.Sleep(2000);
                //Interlocked.Increment()操作是一个原子操作,作用是:iCount++ 具体请看下面说明
                //原子操作,就是不能被更高等级中断抢夺优先的操作。你既然提这个问题,我就说深一点。
                //由于操作系统大部分时间处于开中断状态,
                //所以,一个程序在执行的时候可能被优先级更高的线程中断。
                //而有些操作是不能被中断的,不然会出现无法还原的后果,这时候,这些操作就需要原子操作。
                //就是不能被中断的操作。
                Interlocked.Increment(ref iCount);
                if (iCount == iMaxCount)
                {
                    Console.WriteLine("发出结束信号!");
                    //将事件状态设置为终止状态,允许一个或多个等待线程继续。
                    eventX.Set();
                }
            }
        }
    }
}

输出结果:

C#多线程学习 之 线程池[ThreadPool](转)的更多相关文章

  1. C#多线程学习 之 线程池[ThreadPool]

    在多线程的程序中,经常会出现两种情况: 一种情况:   应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应                   这一般使用ThreadPo ...

  2. [转]C#多线程学习 之 线程池[ThreadPool]

    在多线程的程序中,经常会出现两种情况: 一种情况:   应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应                   这一般使用ThreadPo ...

  3. 多线程系列(2)线程池ThreadPool

    上一篇文章我们总结了多线程最基础的知识点Thread,我们知道了如何开启一个新的异步线程去做一些事情.可是当我们要开启很多线程的时候,如果仍然使用Thread我们需要去管理每一个线程的启动,挂起和终止 ...

  4. python中多进程multiprocessing、多线程threading、线程池threadpool

    浅显点理解:进程就是一个程序,里面的线程就是用来干活的,,,进程大,线程小 一.多线程threading 简单的单线程和多线程运行:一个参数时,后面要加逗号 步骤:for循环,相当于多个线程——t=t ...

  5. 多线程Thread,线程池ThreadPool

    首先我们先增加一个公用方法DoSomethingLong(string name),这个方法下面的举例中都有可能用到 #region Private Method /// <summary> ...

  6. 多线程二:线程池(ThreadPool)

    在上一篇中我们讲解了多线程的一些基本概念,并举了一些例子,在本章中我们将会讲解线程池:ThreadPool. 在开始讲解ThreadPool之前,我们先用下面的例子来回顾一下以前讲过的Thread. ...

  7. Java多线程学习之线程池源码详解

    0.使用线程池的必要性 在生产环境中,如果为每个任务分配一个线程,会造成许多问题: 线程生命周期的开销非常高.线程的创建和销毁都要付出代价.比如,线程的创建需要时间,延迟处理请求.如果请求的到达率非常 ...

  8. 【多线程】Android多线程学习笔记——线程池

    Java线程池采用了享元设计模式,在系统中维持一定数量的线程,用于处理异步或并发需求,在平时处理异步或并发任务时被广泛使用.这里基于JDK1.8和Android28来整理一些关于线程池的知识点. 一. ...

  9. JAVA多线程学习七-线程池

    为什么用线程池 1.创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处理效率 例如: 记创建线程消耗时间T1,执行任务消耗时间T2,销毁线程消耗时间T3 如果T1+T3> ...

随机推荐

  1. [CareerCup] 3.4 Towers of Hanoi 汉诺塔

    3.4 In the classic problem of the Towers of Hanoi, you have 3 towers and N disks of different sizes ...

  2. Fedora 12 环境搭建

    又来折腾发行版了. 这一回是Fedora12,搞的挺艰难的 下载了Fedora-12-i386-DVD.iso,无论使用ultraiso还是dd都无法安装. 后来下载了一个ImageWriter.ex ...

  3. WPF开发时光之痕日记本——终于完工了。。晒晒截图(三)(已上传安装包)

    由于是业余时间学习的 WPF 的相关开发且不怎么会使用 Blend 软件,所以开发这个客户端着实花费了我很长时间,比如文本编辑器的开发,最初是在 Simple.HtmlEditor 的基础上做的修改, ...

  4. 如何将Gate One嵌入我们的Web应用中

    参考文档http://liftoff.github.io/GateOne/Developer/embedding.html 从https://github.com/liftoff/GateOne下载的 ...

  5. AJAX(一)AJAX的简介和基础

    本节简介(异步链接服务器对象)XMLHTTPRequest以及AJAX的简介. AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML). AJ ...

  6. “耐撕”团队2016.04.19站立会议

    1. 时间 : 20:20--20:40  共计20分钟 2. 人员 : Z   郑蕊 * 组长 (博客:http://www.cnblogs.com/zhengrui0452/), P 濮成林(博客 ...

  7. java并发库--锁

    synchronized的缺陷: 被synchronized修饰了,当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁,获取线程被阻塞时,没有释放锁会导致等待线 ...

  8. 设置java jvm(虚拟机) 的内存在大小

    package WanWan; public class Test { /** * @param args */ public static void main(String[] args) { // ...

  9. Productivity Power Tools 动画演示--给力的插件工具

    免费的精品: Productivity Power Tools 动画演示 Productivity Power Tools 是微软官方推出的 Visual Studio 扩展,被用以提高开发人员生产率 ...

  10. 读JS高级(兼容&&BOM&&私有变量&&面向对象)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...