C#多线程编程のTask(任务全面解析)
Task是.NET4.0加入的,跟线程池ThreadPool的功能类似,用Task开启新任务时,会从线程池中调用线程,而Thread每次实例化都会创建一个新的线程。
我们可以说Task是一种基于任务的编程模型。它与thread的主要区别是,它更加方便对线程进程调度和获取线程的执行结果。
Task类和Task<TResult>类
前者接收的是Action委托类型
后者接收的是Func<TResult>委托类型
任务和线程的区别:
1、任务是架构在线程之上的,也就是说任务最终还是要抛给线程去执行。
2、任务跟线程不是一对一的关系,比如开10个任务并不是说会开10个线程,这一点任务有点类似线程池,但是任务相比
线程池有很小的开销和精确的控制。
一、Task的创建
1、直接创建
var task1 = new Task(() =>
{
Console.WriteLine("Begin");
System.Threading.Thread.Sleep();
Console.WriteLine("Finish");
});
Console.WriteLine("Before start:" + task1.Status);
task1.Start();
2、工厂创建
Task.Factory.StartNew(()={
});
3、4.5以后Run运行
Task.Run(()=>{
});
4、一种方便获取返回值的方式
static void Main(string[] args)
{
var tcs = new TaskCompletionSource<int>();
new Thread(() => {
Thread.Sleep();
int i = Enumerable.Range(, ).Sum();
tcs.SetResult(i); }).Start();//线程把运行计算结果,设为tcs的Result。
Task<int> task = tcs.Task;
Console.WriteLine(task.Result); //此处会阻塞,直到匿名线程调用tcs.SetResult(i)完毕
}
二、细节解释
看下面代码:
namespace WpfApplication6
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{ public MainWindow()
{
InitializeComponent();
ConsoleManager.Show();//打开控制台窗口
} private void Window_Loaded(object sender, RoutedEventArgs e)
{
Console.WriteLine("主线程启动");
Task task = Task.Run(() => {
Thread.Sleep(1500);
Console.WriteLine("task启动");
});
Thread.Sleep(300);
task.Wait();
Console.WriteLine("主线程结束");
} }
}
结果:

分析:
开启新任务的方法:Task.Run()或者Task.Factory.StartNew(),开启的是后台线程
要在主线程中等待后台线程执行完毕,可以使用Wait方法(会以同步的方式来执行)。不用Wait则会以异步的方式来执行。
thread和Task的区别,thread new多少个就会创建多少个线程,而task是利用线程池中的线程。
task<TResult>就是有返回值的Task,TResult就是返回值类型。示例:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Console.WriteLine("主线程开始");
//返回值类型为string
Task<string> task = Task<string>.Run(() => {
Thread.Sleep(2000);
return Thread.CurrentThread.ManagedThreadId.ToString();
});
//会等到task执行完毕才会输出;
Console.WriteLine(task.Result);
Console.WriteLine("主线程结束");
}
通过task.Result可以取到返回值,若取值的时候,后台线程还没执行完,则会等待其执行完毕!
简单提一下:
Task任务可以通过CancellationTokenSource类来取消。
三、Task的其他方法
Task.Wait(); //阻塞当前线程
Task.WaitAll(); //阻塞当前线程直到所有的任务执行完毕
Task.WaitAny(); //阻塞当前线程直到有任意一个任务执行完毕 Task.ContinueWith(
task=>{ }); //执行完上一个任务后继续执行,并将上一个任务(包括结果)传递给下一个代码块 一种是使用GetAwaiter方法。GetAwaiter方法返回一个TaskAwaiter结构,该结构有一个OnCompleted事件,只需对 OnCompleted事件赋值,即可在完成后调用该事件。 static void Main(string[] args)
{
Task<int> Task1 = Task.Run<int>(() => { return Enumerable.Range(, ).Sum(); });
var awaiter = Task1.GetAwaiter();
awaiter.OnCompleted(() =>
{
Console.WriteLine("Task1 finished");
int result = awaiter.GetResult();
Console.WriteLine(result); // Writes result
});
Thread.Sleep();
}
四、任务的中断
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
var task = Task.Factory.StartNew(() =>
{
for (var i = ; i < ; i++)
{
System.Threading.Thread.Sleep();
if (token.IsCancellationRequested)
{
Console.WriteLine("Abort mission success!");
return;
}
}
}, token); //注册cancel后要执行的代码
token.Register(() =>
{
Console.WriteLine("Canceled");
});
Console.WriteLine("Press enter to cancel task...");
Console.ReadKey();
//调用取消
tokenSource.Cancel();
五、任务的中断取消
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
var task = Task.Factory.StartNew(() =>
{
for (var i = ; i < ; i++)
{
System.Threading.Thread.Sleep();
if (token.IsCancellationRequested)
{
Console.WriteLine("Abort mission success!");
return;
}
}
}, token); //注册cancel后要执行的代码
token.Register(() =>
{
Console.WriteLine("Canceled");
});
Console.WriteLine("Press enter to cancel task...");
Console.ReadKey();
//调用取消
tokenSource.Cancel();
六、异常处理
异常处理;
对于某些匿名的Task(通过 Task.Run方法生成的,不调用wait,也不关心是否运行完成),某些情况下,记录它们的异 常错误也是有必要的。这些异常称作未观察到的异常(unobserved exceptions)。可以通过订阅一个全局的静态事件 TaskScheduler.UnobservedTaskException来处理这些异常。只要当一个Task有异常,并且在被垃圾回收的时候,才会触 发这一个事件。如果Task还处于被引用状态,或者只要GC不回收这个Task,这个UnobservedTaskException事件就不会被 触发
GC.Collect();
GC.WaitForPendingFinalizers();
七、Task的状态
Created:表示默认初始化任务,但是“工厂创建的”实例直接跳过。
WaitingToRun: 这种状态表示等待任务调度器分配线程给任务执行。
RanToCompletion:任务执行完毕。
C#多线程编程のTask(任务全面解析)的更多相关文章
- .NET面试题解析(07)-多线程编程与线程同步
系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 关于线程的知识点其实是很多的,比如多线程编程.线程上下文.异步编程.线程同步构造.GUI的跨线程访问等等, ...
- .NET面试题解析(07)-多线程编程与线程同步 (转)
http://www.cnblogs.com/anding/p/5301754.html 系列文章目录地址: .NET面试题解析(00)-开篇来谈谈面试 & 系列文章索引 关于线程的知识点其实 ...
- 5天玩转C#并行和多线程编程 —— 第四天 Task进阶
5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...
- 5天玩转C#并行和多线程编程 —— 第三天 认识和使用Task
5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...
- Scalaz(45)- concurrency :Task-函数式多线程编程核心配件
我们在上一节讨论了scalaz Future,我们说它是一个不完善的类型,最起码没有完整的异常处理机制,只能用在构建类库之类的内部环境.如果scalaz在Future类定义中增加异常处理工具的话,用户 ...
- 新手浅谈Task异步编程和Thread多线程编程
初学Task的时候上网搜索,看到很多文章的标题都是task取代thread等等相关,我也一直以为task和thread是一类,其实task是.net4.0提出的异步编程,在之前.net1.0有dele ...
- Linux多线程编程详细解析----条件变量 pthread_cond_t
Linux操作系统下的多线程编程详细解析----条件变量 1.初始化条件变量pthread_cond_init #include <pthread.h> int pthread_cond_ ...
- C#多线程编程(1)--线程,线程池和Task
新开了一个多线程编程系列,该系列主要讲解C#中的多线程编程. 利用多线程的目的有2个: 一是防止UI线程被耗时的程序占用,导致界面卡顿:二是能够利用多核CPU的资源,提高运行效率. 我没有进行很 ...
- 转载 .Net多线程编程—任务Task https://www.cnblogs.com/hdwgxz/p/6258014.html
.Net多线程编程—任务Task 1 System.Threading.Tasks.Task简介 一个Task表示一个异步操作,Task的创建和执行是独立的. 只读属性: 返回值 名称 说明 ob ...
随机推荐
- Javascript继承1:子类的的原型对象----类式继承
//声明父类 function Parent(){ this.parentValue = true; this.favorites = ['看书'] } //为父类添加公有方法 Parent.prot ...
- jquery 树形导航菜单无限级
转自:http://www.jb51.net/article/71615.htm 侵删<!DOCTYPE html> <html lang="en"> &l ...
- RequireJS模块化编程详解
1.模块的写法 模块化编程一般都有这么几个过渡过程,如下描述. 原始方法 function m1(){ //... } function m2(){ //... } 上面的函数m1()和m2(),组成 ...
- BZOJ1101: [POI2007]Zap(莫比乌斯反演)
1101: [POI2007]Zap Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2951 Solved: 1293[Submit][Status ...
- CentOS 7上VNCServer的安装使用
1.安装 yum install tigervnc tigervnc-server 2.配置 vncserver的配置,创建一个新的配置文件 cp /lib/systemd/system/vncser ...
- C# 过滤特殊字符,保留中文,字母,数字,和-
#region public static string FilterChar(string inputValue) 过滤特殊字符,保留中文,字母,数字,和- /// <summary> ...
- <解决方法>Centos安装使用Chromedriver
一.安装Chrome 我安装好Centos系统后,就在网上去找Chrome浏览器的安装方法,使用过yum,rpm都安装不上,会报错,然后询问公司的运维,他给我了个包,然后使用:yum localins ...
- Android Studio多渠道打包(一)
1. 多渠道的概念 APP发布到不同的应用平台,监测用户是从哪个平台安装的. 2. 为什么要多渠道打包 统计用户安装APP来源 批量修改生成的apk文件名 可更改包名 生成不同应用名称或图标 3.多渠 ...
- 计算机网络TCP“三次握手”
终于有时间写这篇文章了,最近真的比较忙! TCP协议 之 “三次握手” 引言:我们知道,TCP是面向连接的协议(相较于UDP无连接的协议),会在传送数据之前先在 发送端 & 接收端 之间建立 ...
- 解决OpenCV JavaCameraView相机preview方向问题
网上找了很多解决都是有问题的,研究了半天源码解决了这个问题.我是从整个相机启动和数据传输的过程着手的,这里捡重点介绍一下,最后会贴上修改后的两个源文件. 首先要知道一个概念. 图里的小圆圈是Home按 ...