C#当中的多线程_任务并行库(下)

时间:2023-03-08 16:53:29

4.8 处理任务中的异常

下面这个例子讨论了任务当中抛出异常,以及任务异常的获取

     class Program
    {
        static void Main(string[] args)
        {
            //声明一个任务
            Task<int> task;
            //第一种方式,普通的try...catch捕获异常
            try
            {
                task = Task.Run(() => TaskMethod("Task 1", ));
                int result = task.Result;
                Console.WriteLine("Result: {0}", result);
            }
            catch (Exception ex)
            {
                //这里捕获的异常是一个被封装的异常,叫做AggregateException
                Console.WriteLine("Exception caught: {0}", ex);
                Console.WriteLine("----------------------------------------------");
                //本例中AggregateException之中只有一个异常,因为只有一个任务抛出了异常
                Console.WriteLine("InnerException is {0}",ex.InnerException.ToString());
            }
            Console.WriteLine("----------------------------------------------");
            Console.WriteLine();             //第二种方式是采用GetAwaiter().GetResult()方法来访问任务结果,这种方式可以提取没有封装的异常
            try
            {
                task = Task.Run(() => TaskMethod("Task 2", ));
                int result = task.GetAwaiter().GetResult();
                Console.WriteLine("Result: {0}", result);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception caught: {0}", ex);
            }
            Console.WriteLine("----------------------------------------------");
            Console.WriteLine();             //第三个demo展示了两个任务抛出异常的情形。
            var t1 = new Task<int>(() => TaskMethod("Task 3", ));
            var t2 = new Task<int>(() => TaskMethod("Task 4", ));
            var complexTask = Task.WhenAll(t1, t2);
            var exceptionHandler = complexTask.ContinueWith(t =>
                    Console.WriteLine("Exception caught: {0}", t.Exception),
                    TaskContinuationOptions.OnlyOnFaulted
                );
            t1.Start();
            t2.Start();             Thread.Sleep(TimeSpan.FromSeconds());
        }         static int TaskMethod(string name, int seconds)
        {
            Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
            Thread.Sleep(TimeSpan.FromSeconds(seconds));
            //抛出一个异常
            throw new Exception("Boom!");
            return * seconds;
        }
   }

结果如下

第一个demo

C#当中的多线程_任务并行库(下)

第二个demo

C#当中的多线程_任务并行库(下)

第三个demo

C#当中的多线程_任务并行库(下)

4.9 并行运行任务
这个小节主要讲述了Task.WhenAll()和Task.WhenAny()这两个方法,一个是等待所有任务全执行后的操作,一个是等待任何一个任务执行完的操作。
例子:
class Program
    {
        static void Main(string[] args)
        {
            //创建两个任务firstTask和secondTask
            var firstTask = new Task<int>(() => TaskMethod("First Task", ));
            var secondTask = new Task<int>(() => TaskMethod("Second Task", ));
            //借助Task.WhenAll()方法创建第三个任务,该任务会在前两个任务完成后完成
            var whenAllTask = Task.WhenAll(firstTask, secondTask);
          //whenAllTask任务结束以后会产生一个结果数组,
          //对应的第一个元素是第一个任务结果,第二个元素对应的是第二个任务结果...
          whenAllTask.ContinueWith(t =>
                Console.WriteLine("The first answer is {0}, the second is {1}", t.Result[], t.Result[]),
                TaskContinuationOptions.OnlyOnRanToCompletion
                );            firstTask.Start();
           secondTask.Start();            Thread.Sleep(TimeSpan.FromSeconds());             //这个demo,展示了启动一系列任务运行的过程
            var tasks = new List<Task<int>>();
            for (int i = ; i < ; i++)
            {
                int counter = i;
                var task = new Task<int>(() => TaskMethod(string.Format("Task {0}", counter), counter));
                tasks.Add(task);
                task.Start();
            }             while (tasks.Count > )
            {
                //使用Task.WhenAny()方法等待任务当中的任何一个任务完成
                var completedTask = Task.WhenAny(tasks).Result;
                //每当一个任务完成,就把他从任务列表移除,直到任务列表为空
                tasks.Remove(completedTask);
                Console.WriteLine("A task has been completed with result {0}.", completedTask.Result);
            }             Thread.Sleep(TimeSpan.FromSeconds());
        }         static int TaskMethod(string name, int seconds)
        {
            Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
            Thread.Sleep(TimeSpan.FromSeconds(seconds));
            return * seconds
}

C#当中的多线程_任务并行库(下)