Task三個列子的分享,Task三個列子分享
這次要分享的是C#Task任務的幾個列子,感覺最實用的是封裝的分頁任務執行方法,這個方法步奏也是目前在我工作中執行多任務常用的,不知道各位也有這用的情況,那麼開始吧。
1.順序任務執行

![]()
1 //順序任務執行
2 Task.Factory.StartNew<int>(() => { Console.WriteLine(1); return 1; }).
3 //等待5s以後才會依次輸出2,3
4 ContinueWith((task) =>
5 {
6
7 Stopwatch wt = new Stopwatch();
8 wt.Start();
9 Thread.Sleep(1000 * 5);
10 wt.Stop();
11 Console.WriteLine("等待了:{0}ms,輸出結果{1}", wt.ElapsedMilliseconds, 2);
12 }).
13 ContinueWith((task) => { Console.WriteLine(3); }).
14 Wait();
View Code
上面的代碼中也備注了一些文字說明,其中有關鍵詞語及意思如下:
.Task.Factory.StartNew:創建一個Task實例,創建後自動開啟,無需在調用Start;
.ContinueWith:看單詞的意思就明了,是繼續的意思,在這裡的效果也是等待上一個Task執行完畢了在繼續執行本次任務,這裡方法裡面每個任務是一層一層傳遞的
效果圖:

這裡有個地方注意,sleep這是了5s但是這裡使用Stopwatch統計出來只有4999ms,這個地方存在差異性,本章不解釋,有興趣朋友可以分享下或研究下。
2.並行任務效果

![]()
1 //並行任務
2 var watch = new Stopwatch();
3 //func方法(認知特點:任意長度參數,最後一個的類型是方法返回的返回值類型)
4 Func<object, int> fun = (num) =>
5 {
6 Thread.Sleep(1000 * 2);
7 Console.WriteLine("第{0}個", num);
8 return Convert.ToInt32(num);
9 };
10 var len = 5;
11 var tasks = new Task<int>[len];
12 //開始計算處理時間
13 watch.Start();
14 for (int _i = 0; _i < len; _i++)
15 {
16 //Task.Factory.StartNew直接開啟Task任務無需在使用start
17 tasks[_i] = Task.Factory.StartNew<int>(fun, _i);
18 }
19 //10s等待
20 Task.WaitAll(tasks, 1000 * 10);
21 watch.Stop();
22 Console.WriteLine("tasks共使用時間:{0}s={1}ms", watch.ElapsedMilliseconds / 1000, watch.ElapsedMilliseconds);
View Code
關鍵詞語及意思如下:
.Func<object, int>這個是C#新增的特性,這個和Action最大的區別就是Func有返回值,其他的和Action相同任意長度參數個數和類型
.Task.WaitAll這個方法有幾個重載,這裡用的是一個超時時間的方法,設置時間後在規定的時間就不繼續等待Task【】了,如果task【】在超時時間范圍內就執行完了,那麼直接通過,不用再等待超時時間
效果:

這裡依然有統計時間查問題,忽略
3.分頁任務執行方法

![]()
1 /// <summary>
2 /// 批次任務執行方法
3 /// </summary>
4 /// <typeparam name="T">參數類型</typeparam>
5 /// <param name="func">func方法</param>
6 /// <param name="list">待執行數據</param>
7 /// <param name="taskLen">任務量</param>
8 /// <param name="timeOut">任務超時時間 默認30s</param>
9 /// <returns></returns>
10 public static int _ExcuteTask<T>(Func<List<T>, int> func, List<T> list, int taskLen = 10, int timeOut = 30) where T : class
11 {
12 var result = 0;
13 //任務量
14 var tasks = new Task<int>[taskLen];
15 var page = list.Count / taskLen + (list.Count % taskLen > 0 ? 1 : 0); //每個分得得需要執行的總條數 最有一個執行剩余所有
16 for (var ji = 1; ji <= taskLen; ji++)
17 {
18 //使用分頁方法獲取待執行數據
19 var list01 = list.Skip((ji - 1) * page).Take(page).ToList();
20 if (list01.Count <= 0) { break; }
21 var task = Task.Run(() =>
22 {
23
24 return func(list01);
25 });
26 tasks[ji - 1] = task;
27 }
28 //等待執行
29 Task.WaitAll(tasks, 1000 * 1 * timeOut);
30 //獲取執行成功條數
31 result = tasks.Where(b => b.IsCompleted).Sum(b => b.Result);
32
33 return result;
34 }
View Code
測試代碼:

![]()
1 /// <summary>
2 /// 測試執行底層數據方法
3 /// </summary>
4 /// <param name="list"></param>
5 /// <returns></returns>
6 static int _FuncTest(List<string> list)
7 {
8
9 foreach (var item in list)
10 {
11 Thread.Sleep(1000 * 2);
12 Console.WriteLine("TaskId:{1}輸出第{0}個值", item, Task.CurrentId);
13 }
14 return list.Count;
15 }
View Code

![]()
1 //分頁任務執行方法
2 var listT = new List<string>();
3 for (int _i = 0; _i < 9; _i++)
4 {
5 listT.Add(_i.ToString());
6 }
7 watch.Restart();
8 //調用任務公共方法
9 var result = _ExcuteTask(_FuncTest, listT, 3);
10 watch.Stop();
11 Console.WriteLine("待處理數據:{0}條,共處理成功數據:{1}條,使用時間:{2}ms", listT.Count, result, watch.ElapsedMilliseconds);
View Code
這裡使用的是分頁的原理,把參數集合分發到創建的Task中,使用Task【】來處理這些數據,這裡和第二個例子有點相識就多了分頁寫法而已,最後統計執行成功的條數,以此來返回給調用者,方便記錄日志,此方法目前是我經常使用的,不知道是否還有更好的,各位多多分享,謝謝。
效果圖:

以上就是這次的總結,希望多同學們有些幫助,有疑問或者問題請及時相互交流。