当前位置: 首页 > news >正文

TPL Part 1 Task 的使用

创建Task

//1. 使用Action
Task task1 = new Task(newAction(printMessage));
// 使用匿名代理
Task task2 = new Task(delegate {
printMessage();
});
// 使用Lambda
Task task3 = new Task(() =>printMessage());
// 使用匿名代理
Task task4 = new Task(() => {
printMessage();
});


 

还可以使用Factory.StartNew()创建Task,区别在于, Factory.StartNew()主要用于创建简单的,生命周期短的Task。无法Start()已经运行的Task,必须创建1个新Task实例然后Start。

同时运行多个Task,Task Scheduler来决定线程的分配以及Task运行时的顺序。

 

设置Task参数

    Task task1 = newTask((msg)=>{
    Console.WriteLine(msg);
    },
"Firsttask");
task1.Start();
Console.ReadLine();


传参,打印。

 

获取Task返回值

Task<int> task1 = new Task<int>(()=> {
Thread.Sleep(3000);
return 1;
});
task1.Start();
Console.WriteLine("Result 1: {0}", task1.Result); //Threadblocked
 
Task<int> task2 = new Task<int>(obj=> {
Thread.Sleep(3000);
return 2;
}, 100);
task2.Start();
Console.WriteLine("Result 2: {0}", task2.Result);
Console.ReadLine();


在获取Task的Result时,会造成线程阻塞,对于上例来说,task1执行完毕时,Task2才开始执行。

取消Task

 

CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
Task task = new Task(() => {
for(int i = 0;i < 5; i++) {
Thread.Sleep(1000);
if(token.IsCancellationRequested) {
Console.WriteLine("Task cancel detected");
throw new OperationCanceledException(token);
} else{
Console.WriteLine("Int value {0}", i);
}
}
},token);
task.Start();
Console.WriteLine("Task started , Press enter to cancel task");
Console.ReadLine();
Console.WriteLine("Cancelling task");
tokenSource.Cancel();


先创建了1个TokenSource,将其中的Token传入Action中,在Action中每秒打印1个数字,直到取消Task时,打印并抛出OperationCaceledException。

对于多个Task的情形,还可以将同一个Token传入它们,就可以一次取消多个Task。

 

监控Task

CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
 
Task task1 = new Task(() => {
for(int i = 0;i < 5; i++) {
if(token.IsCancellationRequested) {
Console.WriteLine("Task cancel detected");
throw new OperationCanceledException(token);
} else{
Console.WriteLine("Int value {0}", i);
}
 
Thread.Sleep(1000);
}
},token);
task1.Start();
Console.WriteLine("Task1 started , Press enter to cancel task");
 
Task task2 = new Task(()=>{
Console.WriteLine("task2 : waiting for task 1 , maximum wait 3 seconds");
token.WaitHandle.WaitOne(3000);
Console.WriteLine("execute task2");
});
task2.Start();
 
Console.ReadLine();
Console.WriteLine("Cancelling task");
tokenSource.Cancel();


在上例中,开启了两个Task,task2需要等待task1执行完毕或被取消才执行,最大等待时间为3秒。

组合取消Task

对于一些情形,会希望传递多个Token的组合,当任意1个Token 取消了Task,就执行取消:

CancellationTokenSource tokenSource1 = new CancellationTokenSource();
CancellationTokenSource tokenSource2 = new CancellationTokenSource();
CancellationTokenSource tokenSource3 = new CancellationTokenSource();
 
CancellationTokenSource compositeSource =
CancellationTokenSource.CreateLinkedTokenSource(
tokenSource1.Token,tokenSource2.Token, tokenSource3.Token);
 
Task task = new Task(() => {
Console.WriteLine("any 1 of 3 token canceled , it will cancel");
compositeSource.Token.WaitHandle.WaitOne();
Console.WriteLine("task canceled");
 
throw new OperationCanceledException(compositeSource.Token);
},compositeSource.Token);
task.Start();
Console.WriteLine("task started and waiting for cancel");
 
Thread.Sleep(1000);
Console.WriteLine("token2 canceling");
tokenSource2.Cancel();
 
Console.ReadLine();


如上例代码所示,3个Token的组合被传入Task中,当Token2取消时,Task被取消,还可以将Token2改为Token1和Token3,不再一一演示。

如果需要在程序外部了解Task是否被Cancel,只需访问IsCanceled属性即可。

等待Task

有时需要在Task外部等待Task执行完毕,可以使用task.Wait()。以下为示例场景:

CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationTokentoken = tokenSource.Token;
 
Task task = new Task(()=>{
Console.WriteLine("task : please wait me for 3 secs to complete in main thread");
for(var i = 0 ;i < 3; i++){
Thread.Sleep(1000);
}
Console.WriteLine("task: complete");
 
},token);
task.Start();
 
Console.WriteLine("main thread: i do some other jobs...");
Thread.Sleep(1000);
Console.WriteLine("main thread: i am ready to wait...");
task.Wait(1500);
 
Console.WriteLine("main thread : i continue some other job...");


如上例所示,在Task要求主线程等待3秒,可在主线程中,最多只能等1.5秒,如果task没结束就直接继续主线程中任务的执行。

等待多个任务

在主线程中,需要等待多个线程都执行完毕的情况:

CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
 
Task task1 = new Task(()=>{
Console.WriteLine("task1 : wait me , main thread");
for(vari = 0 ;i < 3; i++){
Console.WriteLine(string.Format("task1 : {0}/3  done",i+1));
Thread.Sleep(1000);
 
}
Console.WriteLine("task1: complete");
 
},token);
task1.Start();
 
Task task2 = new Task(()=>{
Console.WriteLine("task2 : wait me , main thread");
for(var i = 0 ;i < 2; i++){
Console.WriteLine(string.Format("task2 : {0}/2  done",i+1));
Thread.Sleep(1000);
}
Console.WriteLine("task2: complete");
 
},token);
task2.Start();
 
Console.WriteLine("main thread : waiting for task1 and task2");
Task.WaitAll(task1,task2);
Console.WriteLine("main thread : continue my jobs...");


如果需要等待多个任务,任意1个完成就继续,只需将上述代码中的WaitAll改为WaitAny即可,参数一样。

 

相关文章:

  • 准备移植xynth到arm板上了。
  • TPL - Part 2 异常处理常用方式
  • 一个关于TCHAR的离奇bug
  • C# 使用Xamarin 开发应用 -- 切换Activity
  • Vsual Studio2005打开速度很慢的超级解决方案
  • OO系统分析员之路--用例分析系列(7)--用例规约的编写--业务规则和实体描述[整理重发]...
  • 批量删除多台服务器上的漫游用户配置文件
  • div 长度固定 文字太长实现自动换行
  • 金旭亮博客之“Web开发技术”资源主页
  • TPL Part3 -- 数据共享
  • 如何做软件项目的需求分析....
  • C# Asp.net MVC 分页时传参场景 动态生成QueryString
  • [Windows编程] 使用API函数GetProcAddress的注意事项
  • TPL Part 4 -- Task的协同
  • [Windows编程] SHLWAPI 和 CRT (C Runtime) 字符串处理函数的区别
  • ----------
  • 《深入 React 技术栈》
  • 【技术性】Search知识
  • Android优雅地处理按钮重复点击
  • Centos6.8 使用rpm安装mysql5.7
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • JavaScript服务器推送技术之 WebSocket
  • PHP CLI应用的调试原理
  • V4L2视频输入框架概述
  • 闭包--闭包之tab栏切换(四)
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 基于 Babel 的 npm 包最小化设置
  • 前端攻城师
  • 前端学习笔记之观察者模式
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 通过git安装npm私有模块
  • 用Python写一份独特的元宵节祝福
  • [地铁译]使用SSD缓存应用数据——Moneta项目: 低成本优化的下一代EVCache ...
  • ​linux启动进程的方式
  • ​批处理文件中的errorlevel用法
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • "无招胜有招"nbsp;史上最全的互…
  • #!/usr/bin/python与#!/usr/bin/env python的区别
  • #数学建模# 线性规划问题的Matlab求解
  • (12)Linux 常见的三种进程状态
  • (C语言)逆序输出字符串
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (第一天)包装对象、作用域、创建对象
  • (规划)24届春招和25届暑假实习路线准备规划
  • (算法)N皇后问题
  • (学习日记)2024.01.19
  • (一)Thymeleaf用法——Thymeleaf简介
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (转载)CentOS查看系统信息|CentOS查看命令
  • (总结)Linux下的暴力密码在线破解工具Hydra详解
  • .net 8 发布了,试下微软最近强推的MAUI
  • .NetCore实践篇:分布式监控Zipkin持久化之殇
  • .NET简谈设计模式之(单件模式)