异步编程
Posted 不为失败找借口,只为成功找方法
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了异步编程相关的知识,希望对你有一定的参考价值。
1、async/await特性结构 异步方法:就是在处理完成之前就返回到调用方法。 async/await特性结构由三个部分构成: (1)调用方法:调用异步方法的那个方法,它和异步方法可能在相同的线程,也可能在不同的线程。在异步方法执行其任务的时候继续执行。 class Program { static void Main() { …… Task<int> value=DoAsyncStuff.CalculateSumAsync(5,6); …… } } (2) 异步方法:有异步标识 async static class DoAsyncStuff { public static async Task<int> CalculateSumAsync(int i1,int i2) ----这就是异步方法 有异步标识 async { int sum=await TaskEx.Run( () => GetSum(i1,i2)); return sum; } …… } (3) await 表达式:异步方法内部,指明需要异步执行的任务。一个异步方法至少包含一个await表达式。 2 什么是异步方法 (1)异步方法 async关键字 至少一个await表达式 返回类型:void Task Task<T> 参数不能为out或ref参数 除了方法以外,Lambda表达式和匿名方法也可以作为异步对象。 Task<T>: 如果调用方法要获取一个T类型的值,异步方法的返回类型就必须是Task<T>.调用方法将通过读取Task的Result属性来获取这个T类型的值。这个是有返回参数的返回类型 例如: Task<int> value=DoStuff.CalculateSumAsync(5,6); …… Console.WriteLine("Value : {0}",value.Result); Task: 如果调用方法不需要从异步方法中返回某个值,但需要检查异步方法的状态,那么异步方法可以返回一个Task类型的对象。这时,即使异步方法出现了return语句,也不返回任何东西。例如: Task someTask=DoStuff.CalculateSumAsync(5,6); …… somTask.Wait(); Void:如果调用方法仅仅想执行异步方法,而不需要与它做任何进一步的交互时[这成为[fire and forget]。这时,与上面一样,即使方法中包含return语句也不会返回任何东西。 Demo:使用返回Task<int> 对象的异步方法 classProgram { staticvoid Main(string[] args) { Task<int> value=DoAsyncStuff.CalculateSumAsync(5,6); Console.WriteLine("Value:{0}", value.Result); } } static async Task<int> CalculateSumAsync(int i1, int i2) { int sum = awaitTask.Run(() => GetSum(i1, i2)); return sum; } privatestaticint GetSum(int i1, int i2) { return i1 + i2; } Demo:使用返回Task对象的异步方法 classProgram { staticvoid Main(string[] args) { Task someTask = DoAsyncStuff.CalculateSumAsync1(5, 6); //处理其他事情 someTask.Wait(); Console.WriteLine("Async stuff is done"); Console.ReadLine(); } } publicstaticasyncTask CalculateSumAsync1(int i1, int i2) { int sum = awaitTask.Run(() => GetSum(i1, i2)); Console.WriteLine("Value:{0}", sum); } privatestaticint GetSum(int i1, int i2) { return i1 + i2;} Demo:使用返回void的异步方法 staticvoid Main(string[] args) { DoAsyncStuff.CalculateSumAsync2(5, 6); //处理其他事情 Thread.Sleep(200);----如果这里不暂停当前线程,则会先输出Program Exiting,在输出11 Console.WriteLine("Program Exiting"); } publicstaticasyncvoid CalculateSumAsync2(int i1, int i2) { int sum = awaitTask.Run(() => GetSum(i1, i2)); Console.WriteLine("Value:{0}", sum); } privatestaticint GetSum(int i1, int i2) {return i1 + i2; } 当程序运行到异步方法内部的await表达式时,异步方法会立即创建一个返回类型Task或Task<T>的对象,并返回给调用方法。 调用方法使用Task对象,取其Result属性时,如果异步方法还没有设置该属性,调用方法就暂停等待。 (2)异步方法控制流: privateasyncTask<int> CountCharactersAsync(string uriString) { WebClient wc = newWebClient(); string result = await wc.DownloadStringTaskAsync(uriString); return result.Length; } 上面的异步方法,在遇到await时会立即返回,返回的这个类型与await表达式本身的内容没有关系,会创建一个异步方法返回类型的对象,即Task<int>对象。而异步方法的return语句并没有真正返回某个值,只是退出了。 (3)await表达式 .net 4.5,有大量的异步方法在BCL中。比如上面的DownloadStringTaskAsync方法等。 也可以自己编写异步方法: 使用Task.Run()方法,这个方法是在不同的线程上运行你的方法。 Task.Run的签名:Task Run(Func<TReturn> func) 因此定义异步方法,最重要的就是要创建一个委托。 Demo:使用Task.Run定义await表达式,进而定义异步方法。 classMyClass { publicint Get10() { return 10; } publicasyncTask DoWorkAsync() { Func<int> ten = newFunc<int>(Get10); int a = awaitTask.Run(ten); int b = awaitTask.Run(newFunc<int>(Get10)); int c = awaitTask.Run(() => { return 10; });//该Lambda表达式是与Func<int>兼容的将隐式转换为该委托 Console.WriteLine("{0} {1} {2}", a, b, c); } } staticvoid Main(string[] args) { Task t = (newMyClass()).DoWorkAsync(); Console.WriteLine("111"); t.Wait(); Console.WriteLine("222"); } 结果: Task.Run:
(4)取消一个异步操作 (5)异常处理与await表达式 Task t t.Satus t.IsFaulted (6)在调用方法中同步的等待任务 wait() t.Wait(); Task.WaitAll(); Task.WaitAny(); (7)在异步方法中异步的等待任务 异步等待所有tasks中的任务完成,不会占用主线程的时间。
以上是关于异步编程的主要内容,如果未能解决你的问题,请参考以下文章