1.启动任务
//Framework4.5新增的Task.Run开启一个任务,Run方法中传入一个Action委托 Task.Run(()=> { Thread.Sleep(1000); Console.WriteLine("hello1"); }); Console.WriteLine("abc1"); //Task.Run == Task.Factory.StartNew,后者4.0就可以使用 Task.Factory.StartNew(() => { Thread.Sleep(1000); Console.WriteLine("hello2"); }); Console.WriteLine("abc2");
Console.ReadLine();
Task默认使用线程池中的线程(线程池中的线程为后台线程)。
Task.run()返回一个Task对象,用于监控任务的执行过程。Status属性追踪执行状态
2.等待任务
Task task= Task.Run(()=> { Thread.Sleep(1000); Console.WriteLine("hello1"); }); Console.WriteLine("abc1"); //等待里面task任务结束当前线程再后向下执行,相当于Thread.join() task.Wait(); Console.WriteLine("abc2"); Console.ReadLine();
3.返回值
Task的子类 Task<> 允许任务返回一个值,
Task<string> task = Task.Run(()=>{ Thread.Sleep(3000); return "123"; }); Console.WriteLine("a"); //阻塞 string str = task.Result; Console.WriteLine(str); Console.WriteLine("b"); Console.ReadLine();
task.Result为返回结果。如果当前任务没执行完毕则调用该属性会阻塞当前线程。
4.异常
用try catch捕获任务的异常
release模式下运行
static void Main(string[] args) { Task task = Task.Run(() => throw new Exception("异常")); try { task.Wait(); } catch (Exception e) { Console.WriteLine(e.Message); } Console.ReadLine(); }
5.延迟
方法一、
static void Main(string[] args) { Task<int> task = Task.Run(() => { Thread.Sleep(3000); Console.WriteLine(1); return 999; }); Console.WriteLine(2); var awaiter = task.GetAwaiter(); Console.WriteLine(3); awaiter.OnCompleted(() => { int result = awaiter.GetResult(); Console.WriteLine(result); }); Console.WriteLine(4); Console.ReadLine(); }
awaiter.OnCompleted 表示当上个任务执行完毕时,执行附加的后续任务。
如果先前的任务出现了错误,可以在awaiter.GetResult()的时候重新抛出异常
4以后会等待几秒再显示1和999,
如果不加Console.ReadLine(); 1和999还没来及显示就结束了
方法二、
Task<int> task = Task.Run(() => { Thread.Sleep(3000); Console.WriteLine(1); return 999; }); Console.WriteLine(2); task.ContinueWith(antecedent => { int res = antecedent.Result; Console.WriteLine(res); }); Console.WriteLine(3); Console.ReadLine();
这种方式会返回一个Task对象,它更加适合添加更多的延续。但是如果任务出现错误,我们必须处理AggregateException.
如果需要将延续奉送到UI应用程序上,还需要额外代码
再非UI上下文,若希望延续任务和先导任务执行在同一个线程上,还需要指定TaskContiuationOptions.ExecuteSynchronously,不然它会去请求线程池
ContinueWith更适合并行编程场景
6.另一种创建任务的方法
7.异步等待
static void Main(string[] args) { Program ds = new Program(); Console.WriteLine("111"); ds.ShowDealyAsync(); Console.WriteLine("222"); Console.Read(); } public async void ShowDealyAsync() { Console.WriteLine("333"); await Task.Delay(5000); //执行到await表达式时,立即返回到调用方法,等待5秒后执行后续部分 Console.WriteLine("444"); }
执行到await Task.Delay(5000);时形成分叉路,一方面立即跳回到调用它的方法继续向下执行,同时当前方法等待5秒后向下执行,相当于一个异步版Thread.sheep
显示222一段时间后显示444
异步 lambda表达式
static async Task Main(string[] args) { Func<Task> func = async () => { await Task.Delay(1000); Console.WriteLine("Foo"); }; await func(); Console.WriteLine("abc"); Console.ReadKey(); }
添加到事件的异步
myButton.Click+= async (sender, args) => { await Task.Delay(1000); .... }