.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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM