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中的任务完成,不会占用主线程的时间。