.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;
5 namespace ConsoleApp
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 });
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);
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 };