Task——等待任务完成并获取结果

作者:追风剑情 发布于:2017-10-1 12:38 分类:C#

示例: task.Wait()的使用

using System;
using System.Threading.Tasks;

namespace TastTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //处理Task中未观察到的异常,默认情况下会结束进程。
            //每次当一个Task被垃圾回收时,如果存在一个没有被注意到的异常,CLR
            //的终结器线程就会引发这个事件。一旦引发,就会向你的事件处理方法传递
            //一个UnobservedTaskExceptionEventArgs对象,其中包含你没有注意到的
            //AggregateException
            TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;

            // 创建一个Task(现在还没开始运行)
            Task<Int32> t = new Task<Int32>(n=>Sum((Int32)n), 1000000000);
            // 可以稍后再启动任务
            t.Start();
            // 可选择显式等待任务完成
            // 注意:还有一些重载版本能接受timeout/CancellationToken值
            t.Wait();
            // 可获得结果(Result属性内部会调用Wait)
            Console.WriteLine("The Sum is: "+t.Result);//一个Int32值

            Console.ReadLine();
        }

        private static void OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
        {
            //显示异常堆栈信息
            Console.WriteLine(e.Exception.StackTrace);
            //标记为“已观察到”,这样将阻止该异常触发默认情况下会终止进程的异常升级策略。
            e.SetObserved();
        }

        private static Int32 Sum(Int32 n)
        {
            Int32 sum = 0;
            for (; n > 0; n--)
            {
                try
                {
                    //checked()或checked{}用来检查算术运算是否溢出
                    //并抛出异常
                    //这里如果n太大,会抛出System.OverflowException
                    checked { sum += n; }
                }
                catch (OverflowException e)
                {
                    Console.WriteLine("Int32 sum溢出了");
                }
            }
                
            return sum;
        }
    }
}


重要提示 线程调用Wait方法时,系统检查线程要等待的Task是否已开始执行。如果是,调用Wait的线程会阻塞,直到Task运行结束为止。但如果Task还没开始执行,系统可能(取决于TaskScheduler)使用调用Wait的线程来执行Task。在这种情况下,调用Wait的线程不会阻塞;它会执行Task并立即返回。好处在于,没有线程会被阻塞,所以减少了对资源的占用(因为不需要创建一个线程来替代被阻塞的线程),并提升了性能(因为不需要花时间创建线程,也没有上下文切换)。不好的地方在于,假如线程在调用Wait前已获得了一个线程同步锁,而Task试图获取同一个锁,就会造成死锁的线程


运行测试

11111.png

标签: C#

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号