前面两篇回顾线程和线程池的使用方法, 微软在. NET4.5 推出了新的线程模型 - Task 本篇将简单的介绍 Task 的使用方法
Task 与线程
Task 与线程或者说线程池关系紧密, 可以说是基于线程池实现的, 虽说任务最终还是要抛给线程去执行, 但是 Task 仍然会比线程线程池的开销要小, 并且提供了可靠的 API 来控制线任务执行
使用 Task 来执行的任务最终会交给线程池来执行, 若该任务需要长时间执行, 可以将其标记为 LongRunning, 这是便会单独去请求创建线程来执行该任务
Task
创建
Task 的创建也存在两种方式, 使用 new 或者使用静态工厂方式来创建:
- static void Main(string[] args)
- {
- Task t = new Task(Menthod1);
- t.Start();
- Task.Factory.StartNew(Menthod2);
- Console.WriteLine("主线程的 ID:{0}", Thread.CurrentThread.ManagedThreadId);
- Console.WriteLine("--------------------");
- Console.ReadLine();
- }
- static void Menthod1()
- {
- Thread.Sleep(2000);
- Console.WriteLine("线程 1 的 ID:{0}", Thread.CurrentThread.ManagedThreadId);
- Console.WriteLine("--------------------");
- }
- static void Menthod2()
- {
- Thread.Sleep(4000);
- Console.WriteLine("线程 2 的 ID:{0}", Thread.CurrentThread.ManagedThreadId);
- Console.WriteLine("--------------------");
- }
上面说到使用 Task 执行任务最终还是需要线程池来执行, 若不想让线程池来执行, 可以添加 LongRunning 标志:
- Task t = new Task(Menthod1, TaskCreationOptions.LongRunning);
- t.Start();
- Task.Factory.StartNew(Menthod2, TaskCreationOptions.LongRunning);
TaskCreationOptions 还有很多枚举值, 用来控制任务的更多属性
参数与返回值
使用 Task 也可以传入参数 (object 类型) 与返回值:
- static void Main(string[] args)
- {
- Task.Factory.StartNew(Menthod1, 233);
- //int result = Task.Factory.StartNew(new Func<object, int>(Menthod3), 233).Result;
- Task<int> t = Task.Factory.StartNew(new Func<object, int>(Menthod3), 233);
- int result = t.Result;
- Console.WriteLine("主线程的 ID:{0}", Thread.CurrentThread.ManagedThreadId);
- Console.WriteLine("result:{0}", result);
- Console.WriteLine("--------------------");
- Console.ReadLine();
- }
- static void Menthod1(object obj)
- {
- Thread.Sleep(2000);
- Console.WriteLine("线程 1 的 ID:{0}", Thread.CurrentThread.ManagedThreadId);
- Console.WriteLine("obj:{0}", obj);
- Console.WriteLine("--------------------");
- }
- static int Menthod3(object obj)
- {
- Thread.Sleep(6000);
- Console.WriteLine("线程 3 的 ID:{0}", Thread.CurrentThread.ManagedThreadId);
- Console.WriteLine("obj:{0}", obj);
- Console.WriteLine("--------------------");
- return obj;
- }
这里为了获取返回值, 阻塞了主线程, 这里请注意一下
等待 Task
可以使用 Task 实例的 Wait 方法来实现等待任务结束, 也可以向多线程一样, 使用 WaitAll 和 WaitAny 一样来等待多个任务结束, 不过操作更为简单:
- t.Wait();
- Task.WaitAll(t1, t2...);
- Task.WaitAny(t1, t2...);
取消 Task
任务也是可以事先取消的, 不过需要使用 CancellationTokenSource:
- static void Main(string[] args)
- {
- Task.Factory.StartNew(Menthod1);
- CancellationTokenSource cancelTokenSource = new CancellationTokenSource();
- Task.Factory.StartNew(Menthod2, cancelTokenSource.Token);
- cancelTokenSource.Cancel();
- Console.WriteLine("主线程的 ID:{0}", Thread.CurrentThread.ManagedThreadId);
- Console.WriteLine("--------------------");
- Console.ReadLine();
- }
上述代码就可以将线程 2 给取消掉, 当然, Cancel 方法可以自己找个合适的地方调用
继续 Task
在 Task 中, 可以实现在一个任务结束后开启另一个新的任务:
- static void Main(string[] args)
- {
- Task t = Task.Factory.StartNew(Menthod1);
- t.ContinueWith(new Action<Task>(Menthod4));
- Console.WriteLine("主线程的 ID:{0}", Thread.CurrentThread.ManagedThreadId);
- Console.WriteLine("任务 t 的 ID:{0}", t.Id);
- Console.WriteLine("--------------------");
- Console.ReadLine();
- }
- static void Menthod1()
- {
- Thread.Sleep(2000);
- Console.WriteLine("线程 1 的 ID:{0}", Thread.CurrentThread.ManagedThreadId);
- Console.WriteLine("--------------------");
- }
- static void Menthod4(Task t)
- {
- Console.WriteLine("线程 4 的 ID:{0}", Thread.CurrentThread.ManagedThreadId);
- Console.WriteLine("任务 t 的 ID:{0}", t.Id);
- Console.WriteLine("--------------------");
- }
这里因为使用了委托, 也可以使用 lambda 表达式, 更简单一些调用:
- Task t = Task.Factory.StartNew(Menthod1);
- t.ContinueWith(task =>
- {
- Console.WriteLine("线程 4 的 ID:{0}", Thread.CurrentThread.ManagedThreadId);
- Console.WriteLine("任务 t 的 ID:{0}", task.Id);
- Console.WriteLine("--------------------");
- });
总结
使用传统线程方式来进行多线程编程的时候, 对线程的控制总是不到位, 产生一些奇奇怪怪的问题; 或是代码写得很杂乱; 或是开发人员乱用线程, 比方说无限制的创建线程将线程池线程占满, 等等
Task 的出现, 实现对传统线程操作的封装, 提供可靠高效的 API 来控制线程, 极大的方便多线程编程, 所以可以用到 Task 的地方尽量使用 Task; 当然, 这里仍会产生线程安全的问题, 同样需要进行线程同步, 与上一篇处理方式类似
Task 的内容还有很多, 更深层的运行原理封装还等着我们去了解, 现在只把我用到的东西分享出来, 希望能帮助到需要的人
线程的学习就先告一段落了, 敬请期待新的内容吧
来源: https://www.cnblogs.com/nbclw/p/8441317.html