async await Task 使用方法
使用概述
C#的使用过程中,除了以前的Thread、ThreadPool等用来开一个线程用来处理异步的内容。还可以使用新特性来处理异步。比以前的Thread和AutoResetEvent、delegete一起使用要方便一些。
以前如果使用Thread、AutoResetEvent用来使用异步处理一个任务是如下写发。
static AutoResetEvent a1 = new AutoResetEvent(false); static void Main(string[] args) { Thread th = new Thread(new ThreadStart(method)); th.Start(); Console.WriteLine("start.."+DateTime.Now.ToString("mm:ss fff")); bool isback = a1.WaitOne(2000,false); Console.WriteLine("end .." + DateTime.Now.ToString("mm:ss fff")+ isback); Console.Read(); } //do something static void method() { Thread.Sleep(4000); //超时返回 Console.WriteLine("Async.." + DateTime.Now.ToString("mm:ss fff")); a1.Set(); }
再新开一个线程处理耗时比较长的业务,线程同步用AutoResetEvent来处理,如果超时使用WaitOne来处理,线程间数据传递用Delegate.开的东西比较多,同步的东西也比较多。从.net 4.0开始引入另外一种方法来处理Task,使用的是线程池里的东西,写法比以前方便点。
Task使用
static void Main(string[] args) { Console.WriteLine("main in"); var result = costtime(); Console.WriteLine("back main"); //waittime true 正常返回 false 超时自动过去 bool waittime = result.Wait(1000); Console.WriteLine("main out-" + waittime); Console.Read(); } private static async Task<string> costtime() { Console.WriteLine("cost time in"); await Task.Run(() => { Thread.Sleep(3000); Console.WriteLine("in other method"); }); Console.WriteLine("cost time out"); return "fuck you"; }
测试结果
调用方法异步方法跟普通方法一样使用,不过异步方法一般需要返回支持Task,Task<T>;方法内部耗时方法使用await标志一下。如果是Task为空不需要显式的返回东西。
如果有参数,可以承接异步方法间通讯
var result = costtime();
返回的Task<string>,方法的执行顺序是 主执行到调用,从方法执行到await,返回一个Task标记,然后等待一定时间。超时了主方法执行接下来的动作,不再等待从方法。主方法完成,从方法完成。
result.Wait(1000);
wait如果写入时间就是超时时间,如果不写入时间就是一直等待从方法完成。
主方法不能继续的写法
倘若返回结果稍微写一种方式,可能让主方法设置的超时时间无效
static void Main(string[] args) { Console.WriteLine("main in"); var result = costtime(); Console.WriteLine("back main"); //waittime true 正常返回 false 超时自动过去 bool waittime = result.Wait(1000); Console.WriteLine("main out-" + waittime+"-"+result.Result); Console.Read(); } private static async Task<string> costtime() { Console.WriteLine("cost time in"); await Task.Run(() => { Thread.Sleep(5000); Console.WriteLine("in other method"); }); Console.WriteLine("cost time out"); return "fuckyou"; }
执行程序返回的结果如下
多加了返回的结果,虽然已经超时,也完成超时的状态更新,但是还是不会完整主方法的执行,因为返回的值只是一个标志位,如果主方法要用就得等从方法填充数据。如果没有填充数据,此时是个异常,而结构上不允许。所以如果超时最好自定义返回的数据,否则可能造成一直等待。
一些想法,一些随笔,零零碎碎整理下思路。