前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >.Net4.0如何实现.NET4.5中的Task.Run及Task.Delay方法

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

作者头像
CNXY
发布2017-12-25 14:50:16
1.7K0
发布2017-12-25 14:50:16
举报
文章被收录于专栏:C# 编程C# 编程

前言

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

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

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

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

它有以下两个常用方法:

代码语言:javascript
复制
1 public void SetException(Exception exception);

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

代码语言:javascript
复制
1 public void SetResult(TResult result);

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

一、Task.Run(Action action)方法

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

代码语言:javascript
复制
 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值。

测试代码如下:

代码语言:javascript
复制
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)的泛型版本,实现如下:

代码语言:javascript
复制
 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的返回值。

测试代码如下:

代码语言:javascript
复制
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)方法

代码语言:javascript
复制
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毫秒后返回当前任务,该方法并不会阻塞人任何线程。

测试代码如下:

代码语言:javascript
复制
1             TaskEx.Delay(5000).Wait();
2             Console.WriteLine("Just For Test.");

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

完整代码:

代码语言:javascript
复制
 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 }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-12-29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档