• 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完成。

  • 相关阅读:
    关于xp系统下,IE6/IE8不支持ssl证书站点的原因和解决办法
    C# ?、?? 问号的用法
    shell 字符串处理汇总(查找,替换等等)
    Goland常用快捷键
    Gin框架初识
    go对json对象的生成和解析
    六、编写第一个应用【外部nodejs调用】
    PostmanRESTClient_v0.8.1之chrome插件下载
    linux shell 字符串操作详解 (长度,读取,替换,截取,连接,对比,删除,位置 )
    TPS和QPS的区别和理解
  • 原文地址:https://www.cnblogs.com/NicolasLiaoran/p/12938301.html
Copyright © 2020-2023  润新知