当前位置: 代码迷 >> .NET相关 >> Task的一些用法小结
  详细解决方案

Task的一些用法小结

热度:114   发布时间:2016-04-24 02:59:01.0
Task的一些用法总结

一、Task和多线程以及异常的捕获示例代码:

static void Main(string[] args)        {            // 产生CancellationToken的类,该类允许使用Cancel方法终止线程            // 也可以使用CancellationTokenSource.CreateLinkedTokenSource创建            // 一组相关的Token,任意一个取消都取消            CancellationTokenSource ts = new CancellationTokenSource();                        CancellationToken ct = ts.Token;            Task t = null;            t = new Task(() =>                          {                              for (int i = 1; i < 11; i++)                              {                                  // 调用Cancel方法,状态为true(表示已经取消了)                                  if (!ts.IsCancellationRequested)                                  {                                      if (i == 5)                                      {                                          // 该异常不会直接被主线程捕获                                          throw new Exception("数字是5,非法!");                                      }                                  }                                  else                                  {                                      Console.WriteLine("用户取消");                                      // 抛出异常,强制取消子线程                                      ct.ThrowIfCancellationRequested();                                  }                                  Console.WriteLine(i);                                  Thread.Sleep(500);                              }                          }, ct);            t.Start();            // 注册Cancel之后的引发的事件,注意Exception也可以在这里捕获            t.ContinueWith((task) =>            {                // 只有调用Cancel方法才会被设置为True                Console.WriteLine(t.IsCanceled);                // 无论何种情况,只要完成了就是True                Console.WriteLine(t.IsCompleted);                // 只要有异常,为True(哪怕是ThrowIfCancellationRequested异常)                Console.WriteLine(t.IsFaulted);                // 捕获各种各样的异常                foreach (var item in task.Exception.InnerExceptions)                {                    Console.WriteLine(item.Message);                }            });            Console.ReadLine();            // 取消任务            ts.Cancel();            Thread.Sleep(Timeout.Infinite);        }

结论:

1、无论任何异常都会终止子线程。

2、异常发生之后,只有在Task的Wait/WaitAll/WaitAny/Result或者Continue方法才可以捕获异常,主线程不可能,因为是子线程中的异常。

二、Task的任务先后顺序(允许嵌套任务),同时允许把线程挂接到主线程上执行返回结果(避免以前Thread和WinForm控件交互时候发生的“不是由本线程创建的控件异常……”问题):

static void Main(string[] args)        {            CancellationTokenSource cts = new CancellationTokenSource();            CancellationToken ct = cts.Token;            Task t = new Task(() =>            {                Console.WriteLine("主任务开始……,包含3个子任务:");                Task.Factory.StartNew(() =>                {                    Thread.Sleep(2000);                    Console.WriteLine("任务一");                },                    // 挂接到主线程,这样主线程会自动等待子线程完成后完成                    TaskCreationOptions.AttachedToParent );                Task.Factory.StartNew(() =>                {                    Thread.Sleep(500);                    Console.WriteLine("任务二");                }, TaskCreationOptions.AttachedToParent);                Task.Factory.StartNew(() =>                {                    Thread.Sleep(1000);                    Console.WriteLine("任务三");                },                    TaskCreationOptions.AttachedToParent);            }, ct);            t.ContinueWith((Task) =>            {                Console.WriteLine("子任务都完成,主任务结束。");                // 指定上下文的同步块,防止跨线程访问控件的问题(控制台程序不能使用,WinForm啥可以)            },TaskScheduler.FromCurrentSynchronizationContext());            t.Start();            Thread.Sleep(Timeout.Infinite);        }

相比较原来的Wait而言,不会卡死子线程,而且又可以多任务运行。

欲想知道更多关于线程操作的东西,可以参考:

MSDN,并行处理系列篇:http://msdn.microsoft.com/zh-cn/library/vstudio/3e8s7xdd(v=vs.110).aspx

  相关解决方案