C# 多线程系列(三)
线程池
创建线程需要时间,如果有不同的小任务要完成,就可以事先创建许多线程,在应完成这些任务时发出请求。这个线程数最好在需要更多线程时增加,在需要释放资源时减少。
不需要自己创建这样的一个列表。该列表由ThreadPool类托管。该类会在需要时增加线程池中线程数,直到最大的线程数。
- 可以指定创建线程池时立即启动的最小线程数,以及线程池中可用的最大线程数。
- 如果更多的作业要处理,线程池中的线程个数也到了极限,最新的作业就要排队,且必须等待线程完成其作业。
- 线程池中的线程都是后台线程,不能把入池的线程改为前台线程。
- 不能给入池的线程设置优先级和名字。
- 对于COM对象,入池的所有线程都是多线程单元线程。许多COM对象都需要单线程单元线程。
- 入池的线程只能用于时间比较短的任务。如果线程要一直运行,就应该使用Thread类创建一个线程。
static void Main()
{
int nWorkerThreads;
int nCompletionPorThreads;
ThreadPool.GetMaxThreads(out nWorkerThreads, out nCompletionPorThreads);
//ThreadPool.SetMaxThreads(500, 500);
lib.print("Max worker threads : " + nWorkerThreads);
lib.print("I/O completion threads: " + nCompletionPorThreads); for(int i=; i<; i++)
{
ThreadPool.QueueUserWorkItem(JobForAThread);//将方法排入队列以便执行。 此方法在有线程池线程变得可用时执行。
}
Thread.Sleep();
} static void JobForAThread(object state)
{
for(int i = ; i<; i++)
{
Console.WriteLine("loop {0}, running inside pooled thread {1}", i, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep();
}
}
示例应用程序首先要读取工作线程和I/O线程的最大线程数,把这些信息写入控制台中。接着在for循环中,调用Thread.QueueuserWorkItm()方法,传递一个WaitCallback类型的委托,把JobForAThread()方法赋予线程池中的线程。
线程池收到这个请求后,就会从池中选择一个线程,来调用该方法。如果线程池还没有运行,就会创建一个线程池,并启动第一个线程。如果线程池己经在运行,且有一个空闲线程来完成该任务,就把该作业传递给这个线程。
异步委托
创建线程最简单的方式是定义一个委托,然后异步调用它。
委托使用线程池完成异步任务,当没有前台线程运行时,异步委托将直接结束。
static void Main(string[] args)
{
Action action = new Action(() =>
{
for(int i=; i<; i++)
{
lib.put(".");
Thread.Sleep();
}
}); AsyncCallback calback = (IAsyncResult result) =>
{
Thread.Sleep();
lib.print(result.AsyncState);
};
var rs = action.BeginInvoke(calback, "Begin Invoke");//如此,便启动了异步委托。下面用不同方法等待异步委托完成。 //方法一,用EndInvoke方法,该方法会一直等待,直到委托完成任务为止。
action.EndInvoke(rs); //方法二,使用IAsyncResult相关联的等待句柄。使用AsyncWaitHandle属性可以访问等待句柄。
//这个属性返回一个WaitHandle类型对象,它可以等待委托线程完成其任务。参数是最长等待时间,
//-1表示无限等待。如果当前实例收到信号,则返回为 true;否则为 false。
rs.AsyncWaitHandle.WaitOne(); //方法三,不断检查
while (true)
{
if (!rs.IsCompleted)
{
Thread.Sleep();
}
else
{
break;
}
} //因为callback最终是异步线程回调的,所以,如果直接退出,callback将无法打印出Begin Invoke。
Thread.Sleep();
}
任务
System.Threading.Tasks包含的类抽象出了线程功能,在后台使用ThreadPool。任务表示应完成的某个单元工作,这个单元工作可以在单独的线程中运行,也可以以同步方式启动一个任务,这需要等待主线程。使用任务不仅可以获得一个抽象层,还可以对底层线程进行很多控制。
- 启动任务
可以使用实例化的TaskFactory类,在其中把TaskMethod()方法传递给StarNew()方法,就会立刻启动任务。也可以使用Task类的构造函数。实例化Task对象时,任务不会立即运行,而是指定Created状态。接着调用Task类的Start()方法,来启动任务。使用Task类时,还可以调用TunSynchronously()方法。
static void Main(string[] args)
{
Task t1 = new Task(DoOnFirst);
t1.Start(); TaskFactory tf = new TaskFactory();
Task t2 = tf.StartNew(DoOnFirst); Task t3 = Task.Factory.StartNew(DoOnFirst); Task.WaitAll(t1, t2, t3);
}
static void DoOnFirst()
{
lib.print("Task.CurrentId :" + Task.CurrentId);
lib.print("-----------");
Thread.Sleep();
}
- 连续的任务
连续任务通过在任务上调用ContinueWith()方法类定义。不带TaskContinuationOptions参数,则无论前一个任务是如何结束的,后续任务都启动。也可以用TaskContinuationOptions枚举中的值,来指定连续任务在什么情况下启动。
static object o = new object();
static void Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource();
cts.Token.Register(()=>{
Console.WriteLine("*** token canceled.");
}); Task t1 = new Task(DoOnFirst, cts.Token);
//t1完成的情况下启动t2
Task t2 = t1.ContinueWith(DoOnSecond, TaskContinuationOptions.OnlyOnRanToCompletion);
//t1被取消的情况下启动t3
Task t3 = t1.ContinueWith(DoOnThird, TaskContinuationOptions.OnlyOnCanceled);
try
{
t1.Start();
//cts.Cancel( ); //打开注释,取消了t1,将执行DoOnThird。
}
catch
{
lib.print("t1.IsCanceled : " + t1.IsCanceled);
}
Console.ReadKey();
}
static void DoOnFirst()
{
lock (o)
{
lib.print("Task.CurrentId :" + Task.CurrentId);
lib.print("-----------"); Thread.Sleep();
}
}
static void DoOnSecond(Task t)
{
lock (o)
{
lib.print("task " + t.Id + " finished.");
lib.print("this task id " + Task.CurrentId);
lib.print("-----------"); Thread.Sleep();
}
}
static void DoOnThird(Task t)
{
lock (o)
{
lib.print("task " + t.Id + " Canceld.");
lib.print("this task id " + Task.CurrentId);
lib.print("-----------"); Thread.Sleep();
}
}
任务层次结构
任务也可以构成一个层次结构。一个任务启动一个新任务时,就启动了一个父/子层次结构。
任务的结果
任务结束时,可以把一些有用的状态信息写到共享对象中。也可以使用返回结果的任务返回这些信息。
static void Main(string[] args)
{
Task<int> t1 = new Task<int>((object o)=>{return ;}, "");
t1.Start();
t1.Wait();
lib.print(t1.Result); Task t = new Task(DoParentTask);
t.Start();
}
C# 多线程系列(四)
C# 多线程系列(三)的更多相关文章
- java多线程系列(三)---等待通知机制
等待通知机制 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理解 ...
- (Java多线程系列三)线程间通讯
Java多线程间通讯 多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同. 1.使用wait()和notify()方法在线程中通讯 需求:第一个线程写入(input)用户,另一个线程 ...
- Java多线程系列三——实现线程同步的方法
两种实现线程同步的方法 方法 特性 synchronized 不需要显式地加解锁,易实现 ReentrantLock 需要显式地加解锁,灵活性更好,性能更优秀,结合Condition可实现多种条件锁 ...
- 【Java多线程系列三】实现线程同步的方法
两种实现线程同步的方法 方法 特性 synchronized 不需要显式的加锁,易实现 ReentrantLock 需要显式地加解锁,灵活性更好,性能更优秀,结合Condition可实现多种条件锁 ...
- 多线程系列三:Lock和Condition
有了synchronized为什么还要Lock? 因为Lock和synchronized比较有如下优点 1. 尝试非阻塞地获取锁 2. 获取锁的过程可以被中断 3. 超时获取锁 Lock的标准用法 p ...
- Java多线程系列十——BlockingQueue
参考资料:http://ifeve.com/java-synchronousqueue/http://www.cnblogs.com/jackyuj/archive/2010/11/24/188655 ...
- Java多线程系列--“JUC线程池”04之 线程池原理(三)
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基 ...
- java 多线程系列---JUC原子类(三)之AtomicLongArray原子类
AtomicLongArray介绍和函数列表 在"Java多线程系列--“JUC原子类”02之 AtomicLong原子类"中介绍过,AtomicLong是作用是对长整形进行原子操 ...
- Java多线程系列--“JUC锁”03之 公平锁(一)
概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...
随机推荐
- 【Apache Kafka】二、Kafka安装及简单示例
(一)Apache Kafka安装 1.安装环境与前提条件 安装环境:Ubuntu16.04 前提条件: ubuntu系统下安装好jdk 1.8以上版本,正确配置环境变量 ubuntu系统下安 ...
- Mysql - ORDER BY详解
0 索引 1 概述 2 索引扫描排序和文件排序简介 3 索引扫描排序执行过程分析 4 文件排序 5 补充说明 6 参考资料 1 概述 MySQL有两种方式可以实现ORDER BY: 1.通过索引扫描生 ...
- PHP常用系统设置整理
1.设置时间脚本执行时间 set_time_limit(0); 2.设置最大执行内存 ini_set('memory_limit','1024M');//设置内存 memory_get_usage() ...
- scrapy框架的日志等级和请求传参, 优化效率
目录 scrapy框架的日志等级和请求传参, 优化效率 Scrapy的日志等级 请求传参 如何提高scripy的爬取效率 scrapy框架的日志等级和请求传参, 优化效率 Scrapy的日志等级 在使 ...
- Git:分支的创建、合并、管理和删除
了解分支 如果想实现多人协作.划出Bug区.Feature区等功能,就需要分支功能.(确实很强大的地方) 每次commit时,Git都把它们串成一条时间线,这条时间线就是一个分支.截止到目前,只有一条 ...
- BZOJ 2097 [Usaco2010 Dec]Exercise 奶牛健美操
[题意] 给出一棵树.现在可以在树中删去m条边,使它变成m+1棵树.要求最小化树的直径的最大值. [题解] 二分答案.$Check$的时候用$DP$,记录当前节点每个儿子的直径$v[i]$,如果$v[ ...
- BZOJ 4430 Guessing Camels赌骆驼
[题意概述] 给出三个n的排列,求有多少个数对在三个排列中顺序相同 [题解] 考虑用补集转化的方法,答案为总对数-不满足的对数 一对数不满足条件,当且仅当这对数在两个排列中顺序相同,在另一个排列中的顺 ...
- ganglia3.7.2,web3.7.1安装
1.准备安装包 ganglia-3.7.2-2.el6.x86_64.rpm ganglia-gmetad-3.7.2-2.el6.x86_64.rpm ganglia-gmond-3.7.2-2.e ...
- [bzoj1925][Sdoi2010]地精部落_递推_动态规划
地精部落 bzoj-1925 Sdoi-2010 题目大意:给你一个数n和模数p,求1~n的排列中满足每一个数的旁边两个数,要么一个是边界,要么都比它大,要么都比它小(波浪排列个数) 注释:$1\le ...
- Bran的内核开发指南_中文版
http://www.cnblogs.com/liloke/archive/2011/12/21/2296004.html 最近在看<orange’s>一书,有点想自己写一个轻量级OS的想 ...