.Net 4.5 Task
Task 是 .Net4.0 新出的异步调用方法,粗略看了一下基本对外屏蔽了线程的概念,写异步调用更专注于应用本身。
public class Program { static void Main(string[] args) { //打印主线程 Console.WriteLine("Main thread id is {0}.", Thread.CurrentThread.ManagedThreadId); //创建任务1 var task1 = new Task(() => { Console.WriteLine("Hello, I am task1, thread id:{0}.", Thread.CurrentThread.ManagedThreadId); }); //打印任务1ID Console.WriteLine("Task1 id is {0}.", task1.Id); //任务1的 ContinueWith 使用的 Task 参数就是已经结束的任务, 使用的线程与 task1 也相同 var newtask = task1.ContinueWith((t) => { Console.WriteLine("Task1 status is" + t.Status + ", thread is:{0}, param task id:{1}.", Thread.CurrentThread.ManagedThreadId, t.Id); }); //新任务的ID与task1不同,相当于在线程上顺序执行了2个task Console.WriteLine("Newtask1 id is {0}.", newtask.Id); task1.Start(); //另一种建立任务的方式 var task2 = Task.Factory.StartNew(() => { Console.WriteLine("Hello, I am task2, thread id:{0}.", Thread.CurrentThread.ManagedThreadId); }); Console.WriteLine("Task2 id is {0}.", task2.Id); var task3 = Task.Run(() => { Console.WriteLine("Hello, this is task3. thread id:{0}.", Thread.CurrentThread.ManagedThreadId); }); Console.WriteLine("Task3 id is {0}.", task3.Id); Console.Read(); } }
执行结果:
可以看到:
1. 每种执行异步方法的任务ID都是不同的;
2. task1 与 task 在同一个线程上执行,意味着任务数与线程数并不一一对应,应该是有一个线程池在支持;
3. ContinueWith 会在一个任务执行后紧接着再执行一个任务,后者以前者为参数,但所在线程并不一定相同;
如果需要获取 Task 的返回值,借用一个例子(出处:http://www.teahoo.net/IT/20151031599.html):
public class Program { static void Main(string[] args) { var t1 = Task.Factory.StartNew<List<string>>(() => { return new List<string> { "1", "2", "3" }; }); t1.Wait(); var t2 = Task.Factory.StartNew(() => { Console.WriteLine("t1 返回的数据:" + string.Join(",", t1.Result)); }); Console.Read(); } }
async 与 await 的作用:
先看一个没有使用 async 与 await 的例子:
public class TaskTest { public Task<string> TaskGetString() { return Task.Run<string>(() => { Console.WriteLine("Task is running!"); return "I am here!"; }); } public void TestFunc() { var task = this.TaskGetString(); Console.WriteLine("Test flag."); Console.WriteLine(task.Result); } } public class Program { static void Main(string[] args) { var democlass = new TaskTest(); democlass.TestFunc(); Console.Read(); } }
可以看出先同步打印出了 “TestFlag”,再执行到了 异步任务的内部,打印出 “I am here”。
对代码稍作修改:
public class TaskTest { public async Task<string> TaskGetString() { return await Task.Run<string>(() => { Console.WriteLine("Task is running!"); return "I am here!"; }); } public void TestFunc() { var returnstring = this.TaskGetString(); Console.WriteLine("Test flag."); Console.WriteLine(returnstring); } } public class Program { static void Main(string[] args) { var democlass = new TaskTest(); democlass.TestFunc(); Console.Read(); } }
可以看到 “Test Flag” 出现在 “Task is running” 之后,继而可以看出 async 与 await 的作用来:
1. async 用于声明包含有“异步方法” 的方法,该方法的返回值是 “异步回调的返回值”, 而不是 该方法的返回值;
2. await 用于修饰真正的异步调用,该关键字会将之后的代码封装成一个委托,等异步调用结束后再执行。正因为如此,才能直接获取“异步调用的返回值”;