文章详情页
.Net中Task Parallel Library的进阶用法
在前一篇中,了解了Task的基本用法
如果一个方法返回Task,Task<T>,如何获取Task的返回值,获取值的过程会阻塞线程吗?
static void Main(string[] args){ var result = DoWorkAsync().Result; Console.WriteLine(result); Console.WriteLine("我会什么时候显示"); Console.ReadKey();}static Task<string> DoWorkAsync(){ return Task<string>.Factory.StartNew(() => {Thread.Sleep(3000);return "hello"; });}
可见,Task的Result属性可以获取返回值,而且,获取返回值的过程线程是被阻塞的。
是否可以不阻塞线程,又能拿到某个线程的返回值呢?ContinueWith方法在某个线程结束之后进行,但同时不会阻塞线程。
static void Main(string[] args){ DoWorkAsync().ContinueWith((pre) => {Console.WriteLine(pre.Result); }); Console.WriteLine("我会什么时候显示"); Console.ReadKey();}
但ContinueWith总会在某个线程结束之后进行,是否可以对ContinueWith的过程控制一下呢?
static void Main(string[] args){ DoWorkAsync().ContinueWith((pre) => {Console.WriteLine(pre.Result); }, TaskContinuationOptions.NotOnFaulted); DoWorkAsync().ContinueWith((pre) => {Console.WriteLine(pre.Exception); },TaskContinuationOptions.OnlyOnFaulted); Console.WriteLine("我会什么时候显示"); Console.ReadKey();}
以上,当没有错误的时候就把返回值显示出来,有错误就把错误信息显示出来。
还可以通过Task的实例方法IsCompleted来判断一个线程是否完成。
static void Main(string[] args){ var doWorkTask = DoWorkAsync(); if (doWorkTask.IsCompleted) {Console.WriteLine(doWorkTask.Result); } else {doWorkTask.ContinueWith((pre) =>{ Console.WriteLine(pre.Result);}, TaskContinuationOptions.NotOnFaulted);doWorkTask.ContinueWith((pre) =>{ Console.WriteLine(pre.Exception);}, TaskContinuationOptions.OnlyOnFaulted); } Console.WriteLine("我会什么时候显示"); Console.ReadKey();}
Task的Status属性,以及结合TaskStatus枚举,可以判断Task的状态。
static void Main(string[] args){ var httpClient = new HttpClient(); Task<string> baiduTask = httpClient.GetStringAsync("http://www.baidu.com"); var httpClient2 = new HttpClient(); Task<string> sinaTask = httpClient2.GetStringAsync("http://www.sina.com.cn"); //等上面2个任务完成时这里再开始 Task<string[]> task = Task.WhenAll(baiduTask, sinaTask); task.ContinueWith(stringArray => {//如果任务完成if (task.Status == TaskStatus.RanToCompletion){ for (int i = 0; i < stringArray.Result.Length;i++) {Console.WriteLine(stringArray.Result[i].Substring(0,100)); }}else if (task.Status == TaskStatus.Canceled) //如果被取消{ Console.WriteLine("{0}这个任务被取消了",task.Id);}else //发生错误{ Console.WriteLine("发生错误了~~"); foreach (var item in task.Exception.InnerExceptions) {Console.WriteLine(item.Message); }} }); Console.ReadKey();}
如果要控制Task的生命周期,可以考虑使用TaskCompletionSource<T>。
static void Main(string[] args){ AsyncFactory.GetIntAsync().ContinueWith((prev) => {if (prev.Status == TaskStatus.RanToCompletion){ Console.WriteLine(prev.Result);}else if (prev.Status == TaskStatus.Canceled){ Console.WriteLine("任务被取消");}else{ Console.WriteLine("发生错误哦"); Console.WriteLine(prev.Exception);} }); Console.ReadKey();} } public static class AsyncFactory {public static Task<int> GetIntAsync(){ var tsc = new TaskCompletionSource<int>(); var timer = new System.Timers.Timer(2000); timer.AutoReset = false; timer.Elapsed += (s, e) => {tsc.SetResult(10);timer.Dispose(); }; timer.Start(); return tsc.Task; } }
以上,通过TaskCompletionSource<T>的SetResult给线程设置返回值,通过TaskCompletionSource<T>的.Task有获取了线程。
另外,从.NET 4.5开始,Task的静态方法FromResult,接收T类型,返回Task<T>。
static void Main(string[] args){ var intTask = GetIntAsync(); if (intTask.Status == TaskStatus.RanToCompletion) {Console.WriteLine(intTask.Result); } else if (intTask.Status == TaskStatus.Canceled) {Console.WriteLine("任务被取消"); } else {Console.WriteLine("发生错误哦");Console.WriteLine(intTask.Exception); } Console.ReadKey();}static Task<int> GetIntAsync(){ return Task.FromResult(10);}
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。如果你想了解更多相关内容请查看下面相关链接
标签:
ASP.NET
相关文章:
1. .NET SkiaSharp 生成二维码验证码及指定区域截取方法实现2. .Net Core和RabbitMQ限制循环消费的方法3. asp.net core项目授权流程详解4. ASP.NET Core按用户等级授权的方法5. ASP.NET MVC使用异步Action的方法6. ASP.NET MVC使用jQuery的Load方法加载静态页面及注意事项7. ASP.NET堆和栈三之引用类型对象拷贝和内存分配8. ASP.NET泛型三之使用协变和逆变实现类型转换9. ASP中实现字符部位类似.NET里String对象的PadLeft和PadRight函数10. ASP.NET Core实现中间件的几种方式
排行榜