.Net4.0如何实现.NET4.5中的Task.Run及Task.Delay方法

前言

.NET4.0下是没有Task.Run及Task.Delay方法的,而.NET4.5已经实现,对于还在使用.NET4.0的同学来说,如何在.NET4.0下实现这两个方法呢?

在.NET4.0下,有一个泛型类,叫TaskCompletionSource<TReuslt>,它能控制Task的行为,如给Task设置结果、设置异常、设置取消等。

MSDN是这样描述的(网址):

表示未绑定到委托的 Task<TResult> 的制造者方,并通过Task属性提供对使用者方的访问。

它有以下两个常用方法:

1 public void SetException(Exception exception);

当执行的任务有异常时,可以使用该方法是设置任务的异常。

1 public void SetResult(TResult result);

这是给任务设置一个返回值,如果任务没有返回值,直接设置null即可。

一、Task.Run(Action action)方法

 该方法实现与Task.Factory.StartNew(Action action)类似,实现代码如下:

 1         public static Task Run(Action action)
 2         {
 3             var tcs = new TaskCompletionSource<object>();
 4             new Thread(() => {
 5                 try
 6                 {
 7                     action();
 8                     tcs.SetResult(null);
 9                 }
10                 catch (Exception ex)
11                 {
12                     tcs.SetException(ex);
13                 }
14             }){ IsBackground = true }.Start();
15             return tcs.Task;
16         }

该方法的目的是用来执行委托action所代表的方法,并返回当前所表示的任务,因方法的签名返回值类型为Task,所以需给tcs的SetResult方法设置一个null值。

测试代码如下:

1             TaskEx.Run(() =>
2             {
3                 Thread.Sleep(5000);
4                 Console.WriteLine("Just For Test.");
5             });

该代码的功能是在5s后输出“Just For Test”字符串到控制台。

注:TaskEx是用来封装Run静态方法的一个类,以下内容相同。

二、Task.Run<TResult>(Func<TResult> function)方法

该方法是Task.Run(Action action)的泛型版本,实现如下:

 1         public static Task<TResult> Run<TResult>(Func<TResult> function)
 2         {
 3             var tcs = new TaskCompletionSource<TResult>();
 4             new Thread(() =>
 5             {
 6                 try
 7                 {
 8                     tcs.SetResult(function());
 9                 }
10                 catch (Exception ex)
11                 {
12                     tcs.SetException(ex);
13                 }
14             })
15             { IsBackground = true }.Start();
16             return tcs.Task;
17         }

与Task.Run的非泛型版本类似,该方法的目的是用来执行委托function所代表的方法,并返回当前所表示的任务,该任务类型为Task<TResut>,带有Task的返回值。

测试代码如下:

1             string result = TaskEx.Run(() =>
2             {
3                 Thread.Sleep(5000);
4                 return "Just For Test.";
5             }).Result;
6             Console.WriteLine(result);

该方法的功能与上面的例子一样:在5s后输出“Just For Test”字符串到控制台,但其实现方式不一样,一个用的是Action委托,另外一个使用的是Function<TResult>委托。

二、Task.Delay(int milliSeconds)方法

1         public static Task Delay(int milliseconds)
2         {
3             var tcs = new TaskCompletionSource<object>();
4             var timer = new System.Timers.Timer(milliseconds) { AutoReset = false };
5             timer.Elapsed += delegate { timer.Dispose();tcs.SetResult(null); };
6             timer.Start();
7             return tcs.Task;
8         }

以上代码功能使用了System.Timers.Timer类来实现任务的延时,用来在milliSeconds毫秒后返回当前任务,该方法并不会阻塞人任何线程。

测试代码如下:

1             TaskEx.Delay(5000).Wait();
2             Console.WriteLine("Just For Test.");

该方法的功能还是与前面的两个一样,在5s后输出“Just For Test”字符串到控制台。

完整代码:

 1 using System;
 2 using System.Threading;
 3 using System.Threading.Tasks;
 4 
 5 namespace ConsoleApp
 6 {
 7     class Program
 8     {
 9         static void Main(string[] args)
10         {
11             //Task.Run(Action action)方法
12             TaskEx.Run(() =>
13             {
14                 Thread.Sleep(5000);
15                 Console.WriteLine("Just For Test.");
16             });
17 
18             //Task.Run<TResult>(Func<TResult> function)方法
19             string result = TaskEx.Run(() =>
20             {
21                 Thread.Sleep(5000);
22                 return "Just For Test.";
23             }).Result;
24             Console.WriteLine(result);
25 
26             //Task.Delay(int milliSeconds)方法
27             TaskEx.Delay(5000).Wait();
28             Console.WriteLine("Just For Test.");
29             Console.ReadKey();
30         }
31     }
32     class TaskEx
33     {
34         public static Task Run(Action action)
35         {
36             var tcs = new TaskCompletionSource<object>();
37             new Thread(() => {
38                 try
39                 {
40                     action();
41                     tcs.SetResult(null);
42                 }
43                 catch (Exception ex)
44                 {
45                     tcs.SetException(ex);
46                 }
47             }){ IsBackground = true }.Start();
48             return tcs.Task;
49         }
50         public static Task<TResult> Run<TResult>(Func<TResult> function)
51         {
52             var tcs = new TaskCompletionSource<TResult>();
53             new Thread(() =>
54             {
55                 try
56                 {
57                     tcs.SetResult(function());
58                 }
59                 catch (Exception ex)
60                 {
61                     tcs.SetException(ex);
62                 }
63             })
64             { IsBackground = true }.Start();
65             return tcs.Task;
66         }
67         public static Task Delay(int milliseconds)
68         {
69             var tcs = new TaskCompletionSource<object>();
70             var timer = new System.Timers.Timer(milliseconds) { AutoReset = false };
71             timer.Elapsed += delegate { timer.Dispose();tcs.SetResult(null); };
72             timer.Start();
73             return tcs.Task;
74         }
75     }
76 }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏一块探索区块链

基于Java语言构建区块链(六)—— 交易(Merkle Tree)

在这一系列文章的最开始部分,我们提到过区块链是一个分布式的数据库。那时候,我们决定跳过"分布式"这一环节,并且聚焦于"数据存储"这一环节。到目前为止,我们几乎实...

5528
来自专栏月牙寂

[以太坊源代码分析] II. 数据的呈现和组织,缓存和更新

本文转载来源自:http://blog.csdn.net/teaspring/article/details/75390210 感谢原作者teaspring...

3877
来自专栏丑胖侠

以太坊中以太币及代币计量单位

首先我们来看一下以太币单位之间的转换,以太币的最小单位为wei,1个eth相当于10的8次方wei。通常,大家也使用Gwei作为展示单位。比较常用的就是eth,...

31310
来自专栏余林丰

Spring AOP高级——源码实现(3)AopProxy代理对象之JDK动态代理的创建过程

spring-aop-4.3.7.RELEASE    在《Spring AOP高级——源码实现(1)动态代理技术》中介绍了两种动态代理技术,当然在Spring...

2439
来自专栏Android知识点总结

SpringBoot-08-之统一化json输出与自定义异常捕获

1071
来自专栏黑白安全

以太坊智能合约编码安全之Call注入

Solidity作为一种用于编写以太坊智能合约的图灵完备的语言,除了常见语言特性以外,还提供了调用/继承其他合约的功能。在call、delegatecall、c...

1185
来自专栏汇智网教程

web3.toWei

27610
来自专栏程序你好

.NET面试基础知识

不同公司的职位和工作职责不同。在面试中,工作职责和经验对这个职位很重要。程序员职位有一年的经验他们会关注oops概念、并行编程、算法和解决问题的能力等等。另一方...

762
来自专栏岑玉海

RavenDb学习(三)静态索引

在静态索引这块,RavenDb其实的是lucene,所以里面有很多概念,其实都是lucene本身的。 1.定义静态Indexes documentStore....

3527
来自专栏蘑菇先生的技术笔记

64位进程池HashCode兼容处理

2256

扫码关注云+社区