一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

.Net中TaskParallelLibrary的进阶用法

时间:2026-09-16 09:00:02 编辑:袖梨 来源:一聚教程网

这篇文章介绍了.Net中TaskParallelLibrary的进阶用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

在前一篇中,了解了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.ba**i*du.com");var httpClient2 = new HttpClient();Task<string> sinaTask = httpClient2.GetStringAsync("http://www.s**i*na.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);}

热门栏目