C# Task实现多线程
C# Task实现多线程
C# Task实现多线程一、Task 的优点以及功能
1、在任务启动后,可以随时以任务延续的形式注册回调。
2、通过使用 ContinueWhenAll 和 ContinueWhenAny 方法或者 WaitAll 方法或 WaitAny 方法,协调多个为了响应 Begin_ 方法而执行的操作。
3、在同一Task 对象中封装异步 I/O 绑定和计算绑定操作。
4、监视Task 对象的状态。
5、使用TaskCompletionSource 将操作的状态封送到Task 对象。
二、创建 Task
1、使用构造函数创建
使用Task的构造函数来创建任务,并调用Start方法来启动任务并执行异步操作。
例如
static void Main(string[] args)
{
Console.WriteLine("主线程执行业务处理.");
//创建任务
Task task = new Task(() => {
Console.WriteLine("使用System.Threading.Tasks.Task执行异步操作.");
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
});
//启动任务,并安排到当前任务队列线程中执行任务 (System.Threading.Tasks.TaskScheduler)
task.Start();
Console.WriteLine("主线程执行其他处理");
//主线程挂起1000毫秒,等待任务的完成。
Thread.Sleep(1000);
}
2、使用Task.Factory.StartNew 进行创建Task
Task.Factory 是对Task进行管理,调度管理这一类的。
例如
var task1 = Task.Factory.StartNew(() => DoSomeWork()).ContinueWith(
task => { Console.WriteLine(task.Result.ToString()); }).ContinueWith(
task => { Console.WriteLine(task.Result.ToString()); });
三、等待任务的完成并获取返回值
使用任务执行异步操作时,最主要的是要后的任务完成时的返回值。在任务类中有一个实例方法Wait(有许多重载版本)他能等待任务的完成,我们也可以通过Task类的派生类Task<TResult>创建一个异步任务,并指定任务完成时返回值的类型,这样可以通过Task<TResult>的实例对象获取到任务完成后的返回值。
例如
static void TaskWait() {
//创建任务
Task<int> task = new Task<int>(() =>
{
int sum = 0;
Console.WriteLine("使用Task执行异步操作.");
for (int i = 0; i < 100; i++)
{
sum+=i;
}
return sum;
});
//启动任务,并安排到当前任务队列线程中执行任务(System.Threading.Tasks.TaskScheduler)
task.Start();
Console.WriteLine("主线程执行其他处理");
//等待任务的完成执行过程。
task.Wait();
//获得任务的执行结果
Console.WriteLine("任务执行结果:{0}", task.Result.ToString());
}
四、等待所有线程结束
var task1 = Task.Factory.StartNew(() => DoSomeWork());
var task2 = Task.Factory.StartNew(() => DoSomeWork());
var task3 = Task.Factory.StartNew(() => DoSomeWork());
Task.WaitAll(task1, task2, task3);
五、等待其中一个线程结束
var task1 = Task.Factory.StartNew(() => DoSomeWork());
var task2 = Task.Factory.StartNew(() => DoSomeWork());
var task3 = Task.Factory.StartNew(() => DoSomeWork());
Task.WaitAny(task1, task2, task3);
六、使用ContinueWith方法在任务完成时启动一个新任务
在使用能够Task类的Wait方法等待一个任务时或派生类的Result属性获得任务执行结果都有可能阻塞线程,为了解决这个问题可以使用ContinueWith方法,他能在一个任务完成时自动启动一个新的任务来处理执行结果。
static void TaskContinueWith()
{
//创建一个任务
Task<int> task = new Task<int>(() =>
{
int sum = 0;
Console.WriteLine("使用Task执行异步操作.");
for (int i = 0; i < 100; i++)
{
sum += i;
}
return sum;
});
//启动任务,并安排到当前任务队列线程中执行任务(System.Threading.Tasks.TaskScheduler)
task.Start();
Console.WriteLine("主线程执行其他处理");
//任务完成时执行处理。
Task cwt = task.ContinueWith(t => {
Console.WriteLine("任务完成后的执行结果:{0}", t.Result.ToString());
});
Thread.Sleep(1000);
}
七、创建一组具有相同状态的任务
可以使用TaskFactory类或TaskFactory<TResult>类。这两个类创建一组任务时可以指定任务的CancellationToken、TaskCreationOptions、TaskContinuationOptions和TaskScheduler默认值。
例如
static void TaskFactoryApply()
{
Task parent = new Task(() =>
{
CancellationTokenSource cts = new CancellationTokenSource(5000);
//创建任务工厂
TaskFactory tf = new TaskFactory(cts.Token, TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
//添加一组具有相同状态的子任务
Task[] task = new Task[]{
tf.StartNew(() => { Console.WriteLine("我是任务工厂里的第一个任务。"); }),
tf.StartNew(() => { Console.WriteLine("我是任务工厂里的第二个任务。"); }),
tf.StartNew(() => { Console.WriteLine("我是任务工厂里的第三个任务。"); })
};
});
parent.Start();
Console.Read();
}
八、任务内部实现和任务调度
1、任务内部有一组构成任务状态的属性,标识任务的唯一Id、表示任务的执行状态(TaskStatus)、任务创建时提供的回调函数的引用和传递给回调函数的数据对象AsyncState、对任务创建时的任务调度对象(TaskScheduler)的引用、对父任务的引用以及对执行上下文的引用和ManualResetEventSlim对象的引用。
2、Task类和Task<TResult>类都实现了标准的释放资源的接口,允许在任务完成处理的时候使用Dispose方法释放资源(关闭ManualResetEventSlim对象实例)。
3、可以使用Task类的CurrentId属性获得正在执行的任务的Id,如果没有任务在执行CurrentId返回值为null,CurrentId是一个int?可空类型的属性。
4、任务执行的生命周期通过TaskStatus类型的一个值来表示,TaskStatus所包含的值:
public enum TaskStatus
{
Created = 0,
WaitingForActivation = 1,
WaitingToRun = 2,
Running = 3,
WaitingForChildrenToComplete = 4,
RanToCompletion = 5,
Canceled = 6,
Faulted = 7,
}
5、在任务内部由TaskScheduler类调度任务的执行,该类是一个抽象类,FCL中从他派生了两个派生类:
ThreadPoolTaskScheduler线程池任务调度器
所有任务默认都是采用ThreadPoolTaskScheduler调度任务,他是采用线程池来执行任务,可以通过TaskScheduler类的静态属性Default获得对默认任务调度器的引用。
SynchronizationContextTaskScheduler同步上下文任务调度器
SynchronizationContextTaskScheduler任务调度器能够用在Window form、WPF等应用程序,他的任务调度是采用的GUI线程,所以他能同步更新UI组件,可以通过TaskScheduler类的静态方法FromCurrentSynchronizationContext获得对一个同步上下文任务调度起的引用。
6、例如
private void button1_Click(object sender, EventArgs e)
{
//获得同步上下文任务调度器
TaskScheduler m_syncContextTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
//创建任务,并采用默认任务调度器(线程池任务调度器)执行任务
Task<int> task = new Task<int>(() =>
{
//执行复杂的计算任务。
Thread.Sleep(2000);
int sum = 0;
for (int i = 0; i < 100; i++)
{
sum += i;
}
return sum;
});
var cts=new CancellationTokenSource();
//任务完成时启动一个后续任务,并采用同步上下文任务调度器调度任务更新UI组件。
task.ContinueWith(t => {this.label1.Text="采用SynchronizationContextTaskScheduler任务调度器更新UI。\\r\\n计算结果是:"+task.Result.ToString(); },
cts.Token ,TaskContinuationOptions.AttachedToParent,m_syncContextTaskScheduler);
task.Start();
}
- C# Task实现多线程
- python多线程多种方法(详解python多线程之间的同步一)
- python开启多线程(python 多线程重启方法)
- phpcurl请求能在日志里记录吗(php使用curl模拟多线程实现批处理功能示例)
- python线程池如何实现同步(Python mutiprocessing多线程池pool操作示例)
- php怎么实现多线程(PHP实现的多进程控制demo示例)
- php脚本控制方法(php swoole多进程/多线程用法示例基于php7nts版)
- python中的多线程详解(python多线程抽象编程模型详解)
- python关闭程序强制退出线程(python多线程调用exit无法退出的解决方法)
- python多线程并发使用场景(对python多线程SSH登录并发脚本详解)
- python线程池有几种(对python 多线程中的守护线程与join的用法详解)
- python 多线程与多进程(python 多线程串行和并行的实例)
- python多进程与多线程详解(Python线程之定位与销毁的实现)
- python多线程超时设置(解决python线程卡死的问题)
- python多线程实现(python多线程并发让两个LED同时亮的方法)
- python多线程有两个参数怎么传(python从子线程中获得返回值的方法)
- 记忆中的台词(记忆中的台词)
- 袁冰妍轧戏 拍《琉璃》的同时还在拍《将夜》,难怪被骂演技差(拍琉璃的同时还在拍将夜)
- 刚红就耍大牌,《琉璃》角色滤镜碎一地,心疼工作人员(琉璃角色滤镜碎一地)
- 袁冰妍郑业成这对可以处,有脸红情话他们是真的敢说(袁冰妍郑业成这对可以处)
- 《祝卿好》台词又土又甜,就喜欢这么直接的恋爱(祝卿好台词又土又甜)
- 大女主 汤唯垂青电视圈,搭档朱亚文出演《大明皇妃孙若微传》(汤唯垂青电视圈)
热门推荐
- mysql统计下个月过生日的人数(Mysql出生日期转换为年龄并分组统计人数的方法示例)
- 宝塔怎么设置指定ip访问(宝塔面板如何禁止某个IPIP段访问)
- python找出数组的最大值(Python查找数组中数值和下标相等的元素示例二分查找)
- php错误处理及调试(php报错502 bad gateway解决方法)
- mysqlworkbench怎么设置连接(详解MySQL Workbench使用教程)
- sql server 2012 错误5123(SQL SERVER 9003错误解决方法)
- python3语法规则(详解Python3注释知识点)
- 阿里云ecs服务器数据在哪儿(阿里云ECS云服务器linux系统安装mysql后远程连接不了踩坑)
- 适合小白入门的mysql教程索引简介(一篇带给你MySQL高性能索引)
- php开启curl(解决PHP使用CURL发送GET请求时传递参数的问题)
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9