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();
}
- ftp上传工具使用方法(CuteFTP多线程FTP上传下载工具功能介绍)
- python 多线程与多进程(python 多线程串行和并行的实例)
- python开启多线程(python 多线程重启方法)
- linux多线程怎么设置(超详细讲解Linux C++多线程同步的方式)
- python多线程多进程运行场景(Python多线程同步---文件读写控制方法)
- python中的多线程详解(python多线程抽象编程模型详解)
- python线程池有几种(对python 多线程中的守护线程与join的用法详解)
- python多线程和多进程应用场景(Python多线程处理实例详解单进程/多进程)
- python多线程超时设置(解决python线程卡死的问题)
- python关闭程序强制退出线程(python多线程调用exit无法退出的解决方法)
- php脚本控制方法(php swoole多进程/多线程用法示例基于php7nts版)
- laravel多线程处理请求(Laravel 6 将新增为指定队列任务设置中间件的功能)
- C# Task实现多线程
- php怎么实现多线程(PHP实现的多进程控制demo示例)
- 如何学会python多线程(Python3多线程基础知识点)
- python多线程多种方法(详解python多线程之间的同步一)
- TVB新剧《黯夜守护者》将播,陈展鹏陈炜首次合作探讨人性(TVB新剧黯夜守护者将播)
- 新晋小花被称女版吴卓羲 将取代滕丽名成为TVB新一代御用女警(新晋小花被称女版吴卓羲)
- 艺人吴卓羲10年警察生涯,演足10年阿Sir,系咩玩法(艺人吴卓羲10年警察生涯)
- 菲律宾潜水(菲律宾潜水价格)
- 泰国人妖(变性手术生殖器要割掉吗)
- 泰国美女(泰国人妖和女性如何区分)
热门推荐
- goweb框架哪个用的最多(教你搭建一个简单的Go Web服务器)
- js简单小游戏代码(用JS实现飞机大战小游戏)
- idea如何运行springboot项目(使用idea搭建springboot initializer服务器的问题分析)
- js基础入门到高级教程(浅谈如何循序渐进的学好JS)
- packagejson怎么使用(最全的package.json解析)
- 看门狗主机教程(3分钟学会如何上手supervisor看门狗)
- sqlserver创建带参数的存储过程(SQLServer存储过程实现单条件分页)
- 微信小程序左右翻页效果(微信小程序实现九宫格效果)
- css3动画按钮加光晕效果(CSS3 制作的悬停缩放特效)
- echarts柱状图颜色设置(Echarts基本入门之柱状图、折线图通用配置)
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9