网站/小程序/APP个性化定制开发,二开,改版等服务,加扣:8582-36016

    这篇文章介绍了.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);
    }

    以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。


    评论 0

    暂无评论
    0
    0
    0
    立即
    投稿
    发表
    评论
    返回
    顶部