(65)C# 任务

     

1.启动任务

            //Framework4.5新增的Task.Run开启一个任务,Run方法中传入一个Action委托
            Task.Run(()=> { Thread.Sleep(1000); Console.WriteLine("hello1"); });
            Console.WriteLine("abc1");

            //Task.Run == Task.Factory.StartNew,后者4.0就可以使用
            Task.Factory.StartNew(() => { Thread.Sleep(1000); Console.WriteLine("hello2"); });
            Console.WriteLine("abc2");
Console.ReadLine();

 

 Task默认使用线程池中的线程(线程池中的线程为后台线程)。

Task.run()返回一个Task对象,用于监控任务的执行过程。Status属性追踪执行状态

 

2.等待任务

            Task task= Task.Run(()=> { Thread.Sleep(1000); Console.WriteLine("hello1"); });
            Console.WriteLine("abc1");
            //等待里面task任务结束当前线程再后向下执行,相当于Thread.join()
            task.Wait();
            Console.WriteLine("abc2");
            Console.ReadLine();

 

3.返回值

 

Task的子类 Task<> 允许任务返回一个值,

            Task<string> task = Task.Run(()=>{ Thread.Sleep(3000); return "123"; });
            Console.WriteLine("a");
            //阻塞
            string str = task.Result;
            Console.WriteLine(str);
            Console.WriteLine("b");
            Console.ReadLine();

task.Result为返回结果。如果当前任务没执行完毕则调用该属性会阻塞当前线程。

 

4.异常

用try catch捕获任务的异常

release模式下运行

        static void Main(string[] args)
        {
            Task task = Task.Run(() => throw new Exception("异常"));
            try
            {
                task.Wait();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            Console.ReadLine();
        }



5.延迟

方法一、

        static void Main(string[] args)
        {
            Task<int> task = Task.Run(() => { Thread.Sleep(3000); Console.WriteLine(1); return 999; });
            Console.WriteLine(2);
            var awaiter = task.GetAwaiter();
            Console.WriteLine(3);
            awaiter.OnCompleted(() =>
            {
                int result = awaiter.GetResult();
                Console.WriteLine(result);
            });
            Console.WriteLine(4);
            Console.ReadLine();
        }
awaiter.OnCompleted 表示当上个任务执行完毕时,执行附加的后续任务。
如果先前的任务出现了错误,可以在
awaiter.GetResult()的时候重新抛出异常

 4以后会等待几秒再显示1和999,

如果不加Console.ReadLine(); 1和999还没来及显示就结束了

 

方法二、

            Task<int> task = Task.Run(() => { Thread.Sleep(3000); Console.WriteLine(1); return 999; });
            Console.WriteLine(2);
            task.ContinueWith(antecedent => { int res = antecedent.Result; Console.WriteLine(res); });
            Console.WriteLine(3);
            Console.ReadLine();

这种方式会返回一个Task对象,它更加适合添加更多的延续。但是如果任务出现错误,我们必须处理AggregateException.

如果需要将延续奉送到UI应用程序上,还需要额外代码

再非UI上下文,若希望延续任务和先导任务执行在同一个线程上,还需要指定TaskContiuationOptions.ExecuteSynchronously,不然它会去请求线程池

ContinueWith更适合并行编程场景

 

6.另一种创建任务的方法

 

 

7.异步等待

        static void Main(string[] args)
        {
            Program ds = new Program();
            Console.WriteLine("111");
            ds.ShowDealyAsync();
            Console.WriteLine("222");
            Console.Read();
        }

        public async void ShowDealyAsync()
        {
            Console.WriteLine("333");
            await Task.Delay(5000);  //执行到await表达式时,立即返回到调用方法,等待5秒后执行后续部分
            Console.WriteLine("444");
        }
执行到await Task.Delay(5000);时形成分叉路,一方面立即跳回到调用它的方法继续向下执行,同时当前方法等待5秒后向下执行,相当于一个异步版Thread.sheep

 显示222一段时间后显示444

 

异步 lambda表达式

        static async Task Main(string[] args)
        {
            Func<Task> func = async () => { await Task.Delay(1000); Console.WriteLine("Foo"); };
            await func();
            Console.WriteLine("abc");
            Console.ReadKey();
        } 

 

添加到事件的异步

            myButton.Click+= async (sender, args) => 
            {
                await Task.Delay(1000);
                ....
            }

 

posted @ 2019-11-15 09:29  富坚老贼  阅读(248)  评论(0编辑  收藏  举报