C#中的异步多线程5 在调用方法中同步地等待任务、在异步方法中异步地等待任务

一、在调用方法中同步地等待任务

    static class MyDownloadString
    {
        public static void DoRun()
        {
            Task<int> t = CountCharactersAsync("https://www.baidu.com");
            //t.Wait();
            Console.WriteLine("Main threading");
            
        }
        private static async Task<int> CountCharactersAsync(string site)
        {
            Thread.Sleep(1000);
            string result = await new WebClient().DownloadStringTaskAsync(new Uri(site));
            Console.WriteLine("The task has finished,returning value:{0}", result.Length);
            return result.Length;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            MyDownloadString.DoRun();
            Console.ReadLine();
        }
    }

调用方法虽然可以调用任意多个异步方法并接收他们返回的Task对象,然后代码继续执行其他任务,但在某个点上可能会需要等待某个特殊Task对象完成,然后再继续,参考上面的代码。Task实例提供了一个Wait()方法,可以在Task对象上调用该方法。

在不使用t.Wait()方法时,输出如下:

Main threading
The task has finished,returning value:14462

使用t.Wait()时,输出如下:

The task has finished,returning value:14462
Main threading

可见,Wait使主线程同步地等待任务结束反馈后才输出Main Threading。

Wait方法用于单一Task对象。如果要等待一组Task对象,对于一组Task,WaitAll()可以等待所有任务都结束,WaitAny()可以等待某一个任务结束。

Task<T> t1=AsyncMethod(...);
Task<T> t2=AsyncMethod(...);
...
Task<T>[] tasks=new Tasks<T>[]{t1,t2};
Task.WaitAll(tasks);
//Task.WaitAny(tasks);

 

二、在异步方法中异步地等待任务

有时在异步方法中,会希望用await表达式来等待Task,这时异步方法会返回到调用方法,但该异步方法会等待一个或所有任务完成。可以通过Task.WhenAll()和Task.WhenAny()方法来完成。这两个方法被称为组合子。

Task.WhenAll会异步地等待所有与之相关的Task完成,而不会占用主线程事件。

    class MyDownloadString
    {
        public void DoRun()
        {
            Task<int> t = CountCharactersAsync("https://www.baidu.com", "http://www.sougou.com");
            Console.WriteLine("DoRun:Task {0} finished", t.IsCompleted ? "" : "Not");
            Console.WriteLine("Main thread");
            Console.WriteLine("DoRun:Result={0}", t.Result);
        }
        private async Task<int> CountCharactersAsync(string site1,string site2)
        {
            WebClient wc1 = new WebClient();
            WebClient wc2 = new WebClient();
            Task<string> t1 = wc1.DownloadStringTaskAsync(new Uri(site1));
            Task<string> t2 = wc2.DownloadStringTaskAsync(new Uri(site2));

            List<Task<string>> tasks=new List<Task<string>>();
            tasks.Add(t1);
            tasks.Add(t2);
            await Task.WhenAll(tasks);
            Console.WriteLine("t1 {0} finished",t1.IsCompleted?"":"Not");
            Console.WriteLine("t2 {0} finished",t2.IsCompleted?"":"Not");
            return t1.IsCompleted ? t1.Result.Length : t2.Result.Length;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            MyDownloadString ds = new MyDownloadString();
            ds.DoRun();
            Console.ReadLine();
        }
    }

输出:

DoRun:Task Not finished
Main thread
t1 finished
t2 finished
DoRun:Result=14462

如果换为WhenAny,输出则变为:

DoRun:Task Not finished
Main thread
t1 Not finished
t2 finished
DoRun:Result=16597

Task.WhenAny组合子会异步地等待与之相关的某个Task完成。

posted @ 2020-05-22 18:44  NicolasLiaoRan  阅读(356)  评论(0编辑  收藏  举报