Task类与async/await
2016-07-27 11:34
507 查看
Task 类
Task类是
.NET 4.0之后提供的异步操作抽象,完整路径为
System.Threading.Tasks.Task。
Task类用于表示无返回值的异步操作,对于带有返回值的异步操作应使用
Task类的子类
Task<TResult>。
Task类创建的任务会加入线程池中。
Task/Task<TResult>类的主要构造函数如下:
// 接收Action类型作为异步操作的执行内容 public Task(Action action); // 首参数为带有一个参数的Action<Object>类型,第二参数为要传入的内容 public Task(Action<object> action, object state); // TaskCreationOptions类型为枚举,并设定TaskScheduler的执行策略 public Task(Action action, TaskCreationOptions creationOptions); // 在Task<TResult>类中接收Func<TResult>类型作为异步执行的内容 public Task(Func<TResult> function); public Task(Func<object, TResult> function, object state);
创建完毕的
Task可以使用
Start()方法开始执行:
// 将任务添加到当前的TaskScheduler(任务调度器)中,任务调度器选择合适的时机执行 public void Start(); // 将任务添加到特定的TaskScheduler中 public void Start(TaskScheduler scheduler);
在实际开发中,更多情况下使用
Task类的静态方法
Run()或者工厂类
TaskFactory的成员方法
StartNew()来创建和启动新的任务。
Task类中的一些常用方法:
// 将参数中的异步操作在当前调度器中排队,并返回Task对象 public static Task Run(Action action); public static Task<TResult> Run<TResult>(Func<TResult> function); // 等待Task完成 public void Wait(); //等待当前任务完成 public static void WaitAll(params Task[] tasks); //等待任务数组中的所有任务完成 public static bool WaitAll(Task[] tasks, int millisecondsTimeout;) //等待指定时间
async/await 关键字
C# 5.0之后引入了
async和
await关键字,在语言层面给予了并发更好的支持。
async用于标记异步方法:
async关键字是上下文关键字,只有在修饰方法与Lambda时才会被当作关键字处理,在其它区域将被作为标识符处理。
async关键字可以标记静态方法,但不能标记入口点(
Main()方法)。
async标记的方法返回值必须为
Task、
Task<TResult>、
void其中之一。
await用于等待异步方法的结果:
await关键字同样是上下文关键字,只有在
async标记的方法中才被视为关键字。
await关键字可以用在
async方法和
Task、
Task<TResult>之前,用于等待异步任务执行结束。
一个简单的
async方法结构如下:
async Task testAsync() { ... //顺序执行的内容 return await Task.Run(() => { ... //异步执行的内容 }); }
并不是方法使用
async关键字标记了就是异步方法,直接出现在
async方法内部的语句也是同步执行的,异步执行的内容需要使用
Task类执行。
事实上,一个不包含任何
await语句的
async方法将是同步执行的,此时编译器会给出警告。
简单示例,使用
async/await在屏幕并发输出内容:
using System; using System.Threading; using System.Threading.Tasks; class Program { // Task.Run()方法中的Function是真正异步执行的内容 static async Task<int> Async() => await Task.Run<int>(() => { // 线程ID与Handler()方法不同 Console.WriteLine("Async() Thread ID: [{0}]", Thread.CurrentThread.ManagedThreadId); for (int i = 0; i < 5; i++) { Thread.Sleep(100); Console.WriteLine("Async: Run{0}", i); } Console.WriteLine("Over"); return 666; }); // 返回值为void的async方法AsyncHandler()仅仅是包装器 static async void AsyncHandler() { // 方法体中的内容实际为同步执行,与Main()函数线程ID相同 Console.WriteLine("Handler() Thread ID: [{0}]", Thread.CurrentThread.ManagedThreadId); // 调用异步方法Async()不会阻塞,Async()方法开始异步执行 Task<int> task = Async(); // 每隔0.1s打印输出,此时异步方法Async()也在另一线程中执行,同步打印输出 for (int i = 0; i < 3; i++) { Thread.Sleep(100); Console.WriteLine("Handler: Run{0}", i); } // 在使用await之前的代码都运行在与Main()函数相同的线程 Console.WriteLine("Handler1() Thread ID: [{0}]", Thread.CurrentThread.ManagedThreadId); // AsyncHandler()中的循环执行3次,此时异步方法Async()尚未执行完毕,使用await关键字会阻塞函数 // 在Main()函数中,从调用await开始,AsyncHandler()就已返回了 Console.WriteLine(await task); // 使用await之后的代码运行在Async()方法所处的线程 Console.WriteLine("Handler2() Thread ID: [{0}]", Thread.CurrentThread.ManagedThreadId); // 打印AsyncHandler()函数真正执行完毕信息 Console.WriteLine("Handler Really Finished!"); } // Main方法不能标记为异步 static void Main(string[] args) { Console.WriteLine("Main() Thread ID: [{0}]", Thread.CurrentThread.ManagedThreadId); AsyncHandler(); // 打印AsyncHandler()函数在Main()中已经执行完毕的信息 Console.WriteLine("Handler Finished in Main!"); // AsyncHandler()在实际执行完成之前就返回了,需要阻塞主线程等待AsyncHandler()真正执行完毕 Console.ReadLine(); } }
输出结果:(Mono 4.4.0 && ArchLinux x64)
Main() Thread ID: [1] Handler() Thread ID: [1] Async() Thread ID: [4] Handler: Run0 Async: Run0 Handler: Run1 Async: Run1 Async: Run2 Handler: Run2 Handler1() Thread ID: [1] Handler Finished in Main! Async: Run3 Async: Run4 Over 666 Handler2() Thread ID: [4] Handler Really Finished!
由上述程序中不难看出,在
async关键字标记的异步方法中,使用
await之前的代码都是同步执行的,在调用了
await之后,剩余的代码便异步运行在独立的线程。
相关文章推荐
- 如何在 Linux/Windows/MacOS 上使用 .NET 进行开发
- c#调用COM组件
- 如何在 Linux 中安装微软的 .NET Core SDK
- C#实现把指定数据写入串口
- C#动态创建button的方法
- C#中抽象方法与虚拟方法的区别
- c#中虚函数的相关使用方法
- C#实现给图片加水印的方法
- C#使用加边法计算行列式的值
- C#实现多线程的同步方法实例分析
- C#中尾递归的使用、优化及编译器优化
- C#中的delegate委托类型基本学习教程
- C#实现子窗体与父窗体通信方法实例总结
- C#通用邮件发送类分享
- ruby实现的一个异步文件下载HttpServer实例
- 举例讲解C#中自动实现的属性
- C#中this的用法集锦
- C#数据结构之顺序表(SeqList)实例详解
- C#.NET获取拨号连接的宽带连接方法