这次要分享的是C#Task任务的几个列子,感觉最实用的是封装的分页任务执行方法,这个方法步奏也是目前在我工作中执行多任务常用的,不知道各位也有这用的情况,那么开始吧。
1.顺序任务执行
class="code_img_closed" src="/Upload/Images/2016052505/0015B68B3C38AA5B.gif" alt="" />logs_code_hide('a9a6e368-ad66-4d9f-a746-55744d489cdf',event)" src="/Upload/Images/2016052505/2B1B950FA3DF188F.gif" alt="" />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【】来处理这些数据,这里和第二个例子有点相识就多了分页写法而已,最后统计执行成功的条数,以此来返回给调用者,方便记录日志,此方法目前是我经常使用的,不知道是否还有更好的,各位多多分享,谢谢。
效果图:
以上就是这次的总结,希望多同学们有些帮助,有疑问或者问题请及时相互交流。