一、Task的机制

 
Task位于命名空间System.Threading.Tasks中,是.NET 4.0加入的新模块,其实现机制大致类似于线程池ThreadPool,不过对于ThreadPool来说Task的优势是很明显的:
 
ThreadPool的实现机制:(一对多)
 
1、应用程序拥有一个用于存放委托的全局队列;
2、使用ThreadPool.QueueUserWorkItem将新的委托加入到全局队列;
3、线程池中的多个线程按照先进先出的方式取出委托并执行。
 
Task的实现机制:(多对多)
 
1、应用程序拥有一个用于存放Task(包装的委托)的全局队列(存放主程序创建的Task,标记为了TaskCreationOptions.PreferFairness的Task),以及线程池中每个工作线程对应的本地队列(存放该工作线程创建的Task);
2、使用new Task()或Task.Factory.StartNew将新的Task加入到指定队列;
3、线程池中的多个线程按照优先处理本地队列,其次处理全局队列的方式取出Task并执行;
4、如果工作线程A发现本地队列为空(Task已处理完毕),那么A就会尝试去全局队列中获取Task,如果全局队列也为空,那么A就会到工作线程B的本地队列中“窃取”一个Task来执行,这种策略很明显的使得CPU更加充分的利用了并行执行。
 
 
 

二、Task的使用

 
创建Task并运行:
 
            //新建一个Task
Task t1 = new Task(() => {
Console.WriteLine("Task完成!");
});
//启动Task
t1.Start(); Console.WriteLine("UI线程完成!");

上面是用new关键字创建,等同于如下使用Task.Factory(Task工厂)创建的方式:

 
            //新建一个Task(Task工厂创建,自动启动)
Task t1 = Task.Factory.StartNew(() => {
Console.WriteLine("Task完成!");
}); Console.WriteLine("UI线程完成!");

这里为了简便使用了Lambda表达式(=> 为Lambda运算符),上面两部分代码都等同于如下:

 
            void Test()
{
Console.WriteLine("Task完成!");
} Action action = new Action(Test); //新建一个Task
Task t1 = new Task(action);
//启动Task
t1.Start(); Console.WriteLine("UI线程完成!");

运行效果图:

 
 
Task的执行方式有同步和异步两种,上面的方式很明显是异步执行,我们可以看到做为主线程的UI线程是先一步执行完的。
 
那么要怎么样才能实现Task的同步执行呢?主要就这一个方法:Wait()!
 
代码如下:
 
            //新建一个Task
Task t1 = new Task(() => {
Console.WriteLine("Task完成!");
});
//启动Task
t1.Start(); Console.WriteLine("UI线程开始等待!");//① t1.Wait(); Console.WriteLine("UI线程完成!");//②

运行效果图:

 
 
主线程运行到t1.Wait()时,会读取t1的状态,当发现任务t1还未执行结束时,主线程便会阻塞在这个位置(只是阻塞在t1.Wait()位置,也就是说t1.Wait()之前的代码①照旧执行),当读取到t1的状态为已经执行结束时,主线程才会再次恢复执行,从t1.Wait()之后的位置②继续往下执行。
 
当然,当有多个任务都需要保持同步执行时,可以使用Task.WaitAll方法同时等待多个任务完成,代码如下:
 
            //新建一个Task
Task t1 = new Task(() => {
Console.WriteLine("Task1完成!");
});
//新建一个Task
Task t2 = new Task(() => {
Console.WriteLine("Task2完成!");
});
//启动Task
t1.Start();
t2.Start(); Console.WriteLine("UI线程开始等待!"); //等待t1,t2都完成
Task.WaitAll(t1,t2); Console.WriteLine("UI线程完成!");

运行效果图:

 
 
当然,对于Task的操作还有更多,这里对于我的需求无关紧要,所以不再列举,详情请参见MSDN的API文档:
 
 
 

三、基于Task的异步与延时

 
我在这里进行了如下封装:
 
        /// <summary>
/// 开始一个异步任务
/// </summary>
/// <param name="taskAction">异步任务执行委托</param>
/// <param name="taskEndAction">异步任务执行完毕后的委托(会跳转回UI线程)</param>
/// <param name="control">UI线程的控件</param>
public void StartAsyncTask(Action taskAction, Action taskEndAction, Control control)
{
if (control == null)
{
return;
} Task task = new Task(() => {
try
{
taskAction(); //返回UI线程
control.Invoke(new Action(() =>
{
taskEndAction();
}));
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}); task.Start();
} /// <summary>
/// 开始一个延时任务
/// </summary>
/// <param name="DelayTime">延时时长(秒)</param>
/// <param name="taskEndAction">延时时间完毕之后执行的委托(会跳转回UI线程)</param>
/// <param name="control">UI线程的控件</param>
public void StartDelayTask(int DelayTime, Action taskEndAction, Control control)
{
if (control == null)
{
return;
} Task task = new Task(() => {
try
{
Thread.Sleep(DelayTime * 1000); //返回UI线程
control.Invoke(new Action(() =>
{
taskEndAction();
}));
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}); task.Start();
}

StartAsyncTask主要是执行一个异步操作,并在异步操作完成后执行指定的委托,这里因为Task的执行机制依然是多线程,由于winform的线程安全性使得非UI线程无法访问UI线程中的UI控件,所以在Task操作结束后执行的委托有必要返回到UI线程中,也就是说StartAsyncTask主要的功能就是在taskAction中执行一系列的异步运算,运算结束之后在taskEndAction中进行一些可视化的表现,比如给某某UI控件赋值。

 
StartDelayTask几乎等同于StartAsyncTask,只不过他更加的表现出来一种延时的特性,事实上在StartAsyncTask的taskAction中加入线程Sleep也就是StartDelayTask的效果了。
 
StartAsyncTask的使用,异步耗时操作:
 
            //显示耗时等待界面(比如一串文字:正在加载,请稍等......)
WaitPage.ShowWait(); StartAsyncTask(
() => {
//进行耗时操作......
},
() => {
//耗时操作完成,隐藏耗时等待界面
WaitPage.HideWait();
},
this);

StartDelayTask的使用,异步延时等待:

 
            Console.WriteLine("我军将在三秒后发起反击!");

            StartDelayTask(
//等待的秒数
3,
() => {
//等待结束要做的事
Console.WriteLine("我军开始反击!");
},
this); for (int i = 0; i < 10; i++)
{
Console.WriteLine(String.Format("敌军第{0}轮进攻!",i));
}

运行效果图:

 

C# Winform 基于Task的异步与延时执行的更多相关文章

  1. 实践基于Task的异步模式

    Await 返回该系列目录<基于Task的异步模式--全面介绍> 在API级别,实现没有阻塞的等待的方法是提供callback(回调函数).对于Tasks来说,这是通过像ContinueW ...

  2. 实现基于Task的异步模式

    返回该系列目录<基于Task的异步模式--全面介绍> 生成方法 编译器生成 在.NET Framework 4.5中,C#编译器实现了TAP.任何标有async关键字的方法都是异步方法,编 ...

  3. 基于Task的异步模式的定义

    返回该系列目录<基于Task的异步模式--全面介绍> 命名,参数和返回类型 在TAP(Task-based Asynchronous Pattern)中的异步操作的启动和完成是通过一个单独 ...

  4. 基于Task的异步模式--全面介绍

    今天是国庆长假第一天,也是今天十月的开始.每到这个时候都是看海的季节-一个看"人海"的季节.反正我是不想在这样一个尴尬期出去放松自己,于是不如在家写写博客,长点本领呢.今天就来给大 ...

  5. .Net Core WebAPI 基于Task的同步&异步编程快速入门

    .Net Core WebAPI 基于Task的同步&异步编程快速入门 Task.Result async & await 总结 并行任务(Task)以及基于Task的异步编程(asy ...

  6. Task的异步模式

    Task的异步模式 返回该系列目录<基于Task的异步模式--全面介绍> 生成方法 编译器生成 在.NET Framework 4.5中,C#编译器实现了TAP.任何标有async关键字的 ...

  7. C#5.0之后推荐使用TPL(Task Parallel Libray 任务并行库) 和PLINQ(Parallel LINQ, 并行Linq). 其次是TAP(Task-based Asynchronous Pattern, 基于任务的异步模式)

    学习书籍: <C#本质论> 1--C#5.0之后推荐使用TPL(Task Parallel Libray 任务并行库) 和PLINQ(Parallel LINQ, 并行Linq). 其次是 ...

  8. C#深度学习のTask(基于任务的异步模型)

    一.Task关键字解释 Task 类的表示的单个操作不会返回一个值,通常以异步方式执行. Task 对象是一种的中心思想 基于任务的异步编程模式 首次引入.NET Framework 4 中. 因为由 ...

  9. 15.6.1 【Task使用】基于任务的异步模式

    C# 5异步函数特性的一大好处是,它为异步提供了一致的方案.但如果在命名异步方法以及 触发异常等方面做法存在着差异,则很容易破坏这种一致性.微软因此发布了基于任务的异步模 式(Task-based A ...

随机推荐

  1. 使用Istio治理微服务入门

    近两年微服务架构流行,主流互联网厂商内部都已经微服务化,初创企业虽然技术积淀不行,但也通过各种开源工具拥抱微服务.再加上容器技术赋能,Kubernetes又添了一把火,微服务架构已然成为当前软件架构设 ...

  2. js父页面和子页面之间传值

    今天和朋友一块讨论,怎样通过js在父页面和子页面之间传值的问题,总结例如以下: 需求描写叙述:父页面有多个子页面.实如今父页面点击子页面,传值到子页面. 看着非常easy,试了好久.主要纠结在怎样获取 ...

  3. -[ASIDataCompressor compressBytes:length:error:shouldFinish:] in ASIDataCompressor.o

    本文转载至 http://blog.csdn.net/m372897500/article/details/38293973 -[ASIDataCompressor compressBytes:len ...

  4. 安装PyTorch 0.4.0

    https://blog.csdn.net/sunqiande88/article/details/80085569 https://blog.csdn.net/xiangxianghehe/arti ...

  5. webview300毫秒点击问题

    http://www.jshacker.com/note/3585 http://blog.csdn.net/zfy865628361/article/details/49512095 http:// ...

  6. 阿里巴巴fastjson 包的使用解析json数据

    Fastjson是一个Java语言编写的高性能功能完善的JSON库.由阿里巴巴公司团队开发的. 主要特性主要体现在以下几个方面: 1.高性能 fastjson采用独创的算法,将parse的速度提升到极 ...

  7. WCF基础之数据协定

    数据协定最重要的当然就是DataContract和DataMember.这两个特性能应用到类.结构和枚举.这个两个特性跟服务契约的特点是一样的,只有被DataContract标记的类和类中被标记Dat ...

  8. 加密php源代码

    <?php function RandAbc($length = "") { //返回随机字符串 $str = "ABCDEFGHIJKLMNOPQRSTUVWXY ...

  9. 【学员管理系统】0x04 数据库连接优化

    [学员管理系统]0x04  pymysql数据库连接优化 写在前面 项目详细需求参见:Django项目之[学员管理系统] 优化实现 把操作封装成函数 我们之前使用pymysql操作数据库的操作都是写死 ...

  10. 关于中国省市的一份js代码

    下面是一份关于中国省市的js代码,搜藏起来,非常有用. var arrCity = [ { name:"请选择", sub:[{name:"请选择"}], ty ...