【多线程】Task
介绍
Task是.NET推出数据任务处理的工作类。位于System.Threading.Tasks命名空间下,通过命名空间也可以看出是个多线程类。
创建Task:
Task有很多构造函数,无参有参都有,想了解更多可以去官网查看。这里只介绍经常用的形式。
第一种:以类的实例化形式进行创建Task。通过实例化一个Task对象,然后Start,这种方式中规中矩。
Task Task1 = new Task(() => Console.WriteLine("Task")); Task1.Start();
第二种:在实践中通常使用这种简洁形式,这种直接运行了Task不需要在start调用
Task.Run(() => Console.WriteLine("Task"));
第三种:通过Task的静态属性创建,然后直接启动。Factory提供对用于创建 Task 和 Task<TResult> 的工厂方法的访问。
var t1= Task.Factory.StartNew(() => { Console.WriteLine("Task"); });
StartNew和Run区别
这两个应用的场景都是一样的,只不过Run是StartNew的再次封装吧,与之相比Run比StartNew自动执行了Unwrap。
Unwrap:主要的作用就是会把嵌套在Task或者Task<>的结果提取出来。
判断执行状态:
通过IsCompleted属性可以查看当前task是否执行完成。
var t11 = Task.Factory.StartNew(() => { Console.WriteLine("Task"); }); if (t11.IsCompleted) { Console.WriteLine("线程已经完成"); }
等待控制:
通过WhenAny和WhenAll来控制等待,WhenAny表示任意一个Task完成之后,返回这个Task对象,但是有时候我们需要等待任务的完成,WhenAll表示处理完成之后,返回所有对象实例。例如:
List<Task<string>> TaskList = new List<Task<string>>() { Task.Factory.StartNew(()=> { return WriteHello(10); },C1.Token), Task.Factory.StartNew(()=> { return WriteHello(20); },C1.Token), Task.Factory.StartNew(()=> { return WriteHello(30); },C1.Token), Task.Factory.StartNew(()=> { return WriteHello(40); },C1.Token) }; //var Reuslt= await Task.WhenAll(TaskList); var Reuslt = await Task.WhenAny(TaskList); if (Reuslt.IsCompleted) { Console.WriteLine("有人完成了"); }
等待的时候,要加上async 和 await;
以上是异步等待,要想实现同步操作使用AwaitAll
var t1 = Task.Factory.StartNew(() => { Console.WriteLine("Task1"); }); var t2 = Task.Factory.StartNew(() => { Console.WriteLine("Task2"); }); var t3 = Task.Factory.StartNew(() => { Console.WriteLine("Task3"); }); //等待并行完成 Task.WaitAll(t1, t2, t2, t3);
此时只有执行完成所有task后才会执行下面的代码。
死锁问题
此代码仅作保存研究
出现死锁:
#region 并行死锁问题 public static void ParallelLock() { var t1 = Task.Factory.StartNew(() => { Console.WriteLine("Task 1 Start running..."); while (true) { System.Threading.Thread.Sleep(1000); } Console.WriteLine("Task 1 Finished!"); }); var t2 = Task.Factory.StartNew(() => { Console.WriteLine("Task 2 Start running..."); System.Threading.Thread.Sleep(2000); Console.WriteLine("Task 2 Finished!"); }); Task.WaitAll(t1, t2); } #endregion
解决办法:
#region 解决死锁问题 /// <summary> /// 解决死锁问题设置时间 /// </summary> public static void ParallelLockEnd() { Task[] tasks = new Task[2]; tasks[0] = Task.Factory.StartNew(() => { Console.WriteLine("Task 1 Start running..."); while (true) { System.Threading.Thread.Sleep(1000); } Console.WriteLine("Task 1 Finished!"); }); tasks[1] = Task.Factory.StartNew(() => { Console.WriteLine("Task 2 Start running..."); System.Threading.Thread.Sleep(2000); Console.WriteLine("Task 2 Finished!"); }); Task.WaitAll(tasks, 5000); for (int i = 0; i < tasks.Length; i++) { if (tasks[i].Status != TaskStatus.RanToCompletion) { Console.WriteLine("Task {0} Error!", i + 1); } } Console.Read(); } #endregion
作者:YanBigFeg —— 颜秉锋
出处:http://www.cnblogs.com/yanbigfeg
本文版权归作者和博客园共有,欢迎转载,转载请标明出处。如果您觉得本篇博文对您有所收获,觉得小弟还算用心,请点击右下角的 [推荐],谢谢!