C#多线程学习 之 线程池[ThreadPool](转)
在多线程的程序中,经常会出现两种情况:
一种情况: 应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应
这一般使用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(); 将事件状态设置为终止状态,允许一个或多个等待线程继续。
修改后的程序:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859using
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](转)的更多相关文章
- C#多线程学习 之 线程池[ThreadPool]
在多线程的程序中,经常会出现两种情况: 一种情况: 应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应 这一般使用ThreadPo ...
- [转]C#多线程学习 之 线程池[ThreadPool]
在多线程的程序中,经常会出现两种情况: 一种情况: 应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应 这一般使用ThreadPo ...
- 多线程系列(2)线程池ThreadPool
上一篇文章我们总结了多线程最基础的知识点Thread,我们知道了如何开启一个新的异步线程去做一些事情.可是当我们要开启很多线程的时候,如果仍然使用Thread我们需要去管理每一个线程的启动,挂起和终止 ...
- python中多进程multiprocessing、多线程threading、线程池threadpool
浅显点理解:进程就是一个程序,里面的线程就是用来干活的,,,进程大,线程小 一.多线程threading 简单的单线程和多线程运行:一个参数时,后面要加逗号 步骤:for循环,相当于多个线程——t=t ...
- 多线程Thread,线程池ThreadPool
首先我们先增加一个公用方法DoSomethingLong(string name),这个方法下面的举例中都有可能用到 #region Private Method /// <summary> ...
- 多线程二:线程池(ThreadPool)
在上一篇中我们讲解了多线程的一些基本概念,并举了一些例子,在本章中我们将会讲解线程池:ThreadPool. 在开始讲解ThreadPool之前,我们先用下面的例子来回顾一下以前讲过的Thread. ...
- Java多线程学习之线程池源码详解
0.使用线程池的必要性 在生产环境中,如果为每个任务分配一个线程,会造成许多问题: 线程生命周期的开销非常高.线程的创建和销毁都要付出代价.比如,线程的创建需要时间,延迟处理请求.如果请求的到达率非常 ...
- 【多线程】Android多线程学习笔记——线程池
Java线程池采用了享元设计模式,在系统中维持一定数量的线程,用于处理异步或并发需求,在平时处理异步或并发任务时被广泛使用.这里基于JDK1.8和Android28来整理一些关于线程池的知识点. 一. ...
- JAVA多线程学习七-线程池
为什么用线程池 1.创建/销毁线程伴随着系统开销,过于频繁的创建/销毁线程,会很大程度上影响处理效率 例如: 记创建线程消耗时间T1,执行任务消耗时间T2,销毁线程消耗时间T3 如果T1+T3> ...
随机推荐
- 北京联想招聘-Android高级工程师(5-7年) 加入qq 群:220486180 或者直接在此 留言咨询
Job ID #: 47979 Position Title: 高级Android开发工程师 Location: CHN-Beijing Functional Area: Research/Devel ...
- display:inline-block的坑
一直用display:inline-block做某种导航栏还很爽,突然有一个柱状图的需求便也这么做了,于是成功被坑. 简简单单个需求,大致这样 只用几个li加上display:inline-block ...
- 【Lucene实验1】构建索引
一.实验名称:构建索引 二.实验日期:2013/9/21 三.实验目的: 1) 能理解Lucene中的Document-Field结构的数据建模过程: 2) 能编针对特定数 ...
- dom4j 使用总结
dom4j是一个Java的XML API,类似于jdom,用来读写XML文件 dom4j的使用方法简单总结来说如下: ①可以创建一个新的xml文件 ②利用SAXReader和File对象创建一个已存在 ...
- css限制图片大小,避免页面撑爆
/*==========限制图片大小======避免页面撑暴========*/img { max-width:100%;width:expression(width>669?"100 ...
- android之外部文件存储和读取
这次借用上次读写内部存储的代码,只是对将更换文件的读写路径即可.这里需要对获取SDcard的读写权限. 一.AndroidManifest.xml 这里增加了对外部存储设备的读写权限 <?xml ...
- 8、面向对象以及winform的简单运用(事件与winform入门)
事件 Visual studio中对可视化窗体控件的事件处理机理: 所有的.NET Framework可视化窗体控件的预定义事件,都会某一对应的“事件名+Handler”委托类型的变量.与此事件相关的 ...
- [转]Oracle数据库中的约束
SQL 约束 约束用于限制加入表的数据的类型. 可以在创建表时规定约束(通过 CREATE TABLE 语句),或者在表创建之后也可以(通过 ALTER TABLE 语句). 我们将主要探讨以下几种约 ...
- 使用Owin中间件搭建OAuth2.0认证授权服务器
前言 这里主要总结下本人最近半个月关于搭建OAuth2.0服务器工作的经验.至于为何需要OAuth2.0.为何是Owin.什么是Owin等问题,不再赘述.我假定读者是使用Asp.Net,并需要搭建OA ...
- 【kAriOJ】离散数学春季学期编程测试 1
A.凯撒密码 题意: 给你k1,k2,和一串明文,一串密文. 明文用k1加密,密文用k2解密. 对于明文要把字母转换成大写字母,非字母全部删除. 额:要考虑到取模可能会变成负数,所以要加一下26再取模 ...