.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 条评论
登录 后参与评论

相关文章

来自专栏芋道源码1024

Java初中级面试题(2)

2017
来自专栏崔庆才的专栏

爬虫速度太慢?来试试用异步协程提速吧!

在执行一些 IO 密集型任务的时候,程序常常会因为等待 IO 而阻塞。比如在网络爬虫中,如果我们使用 requests 库来进行请求的话,如果网站响应速度过慢,...

1430
来自专栏分布式系统和大数据处理

C#中的委托和事件 - Part.2

如果你看过了 C#中的委托和事件 一文,我想你对委托和事件已经有了一个基本的认识。但那些远不是委托和事件的全部内容,还有很多的地方没有涉及。本文将讨论委托和事件...

962
来自专栏GreenLeaves

C# 委托进阶

本文参考自:https://wenku.baidu.com/view/41ab91d3c1c708a1284a44d7.html?qq-pf-to=pcqq.c...

1796
来自专栏河湾欢儿的专栏

event事件对象

event: 事件对象,当一个事件发生的时候,和当前这个对象发生的这个事件有关的一些详细信息都会被临时保存到一个指定的地方-event对象,供我们在需要的时候调...

582
来自专栏java思维导图

Java中高级面试题部分答案解析(2)

这里是一些题型解析,还是这些话:不一定全部正确,有一些是没有固定答案的,如果发现有错的或者更适合的答案欢迎留言矫正。

541
来自专栏BY的专栏

GCD 在 Swift 中的用法

3275
来自专栏FD的专栏

一步步理解python的异步IO

看到越来越多的大佬都在使用python的异步IO,协程等概念来实现高效的IO处理过程,可是我对这些概念还不太懂,就学习了一下。 因为是初学者,在理解上有很多不到...

972
来自专栏Python专栏

用python帮助你从此快起来!

1326
来自专栏我爱编程

Day26异步IO

协程 协程,又称微线程,纤程。英文名Coroutine。 协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当的时候再返回来...

2464

扫码关注云+社区