zoukankan      html  css  js  c++  java
  • 异步编程基础

      本质上适合异步的操作有:HTTP请求,数据库指令,Web服务调用等。

    1、暂停一段时间(以异步方式)。

      以异步的方式暂停一段时间,这在进行单元测试或者重试延迟时非常有用。

      Task类有一个返回Task对象的静态函数Delay,下面是其中的一个

            public static Task Delay(TimeSpan delay)
            {
                return Task.Delay(delay,     default(CancellationToken));
            }    

    一个简单的指数退避。指数退避是一种重试策略,重试的延迟时间会逐次增加。在访问web服务时可采用指数退避,它可以防止服务器被太多的重试阻塞。

      private async Task<string> DownLoadString(string url)
            {
                using (var client = new HttpClient())
                {
                    //第一次重试前等1秒,第二次重试前等2秒,第三次重试前等4次
                    var nextDelay = TimeSpan.FromSeconds(1);
                    for (int i = 0; i < 3; i++)
                    {
                        try
                        {
                            return await client.GetStringAsync(url);
                        }
                        catch
                        {
                        }
                        await Task.Delay(nextDelay);
                        nextDelay = nextDelay + nextDelay;
                    }
                    //最后一次调用,以便让调用者知道出错信息
                    return await client.GetStringAsync(url);
                }
            }

      总结:Task.Delay 适合用于对异步代码进行单元测试或者实现重试逻辑。

    2、返回完成的任务 Task.FromResult

      当要实现一个既有异步签名的同步方法  或者 对异步代码进行单元测试时,都可以使用Task.FromResult。

      Task.FromResult方法创建并返回一个新的Task<T>对象,这个Task对象是已完成,并具有特定的值。

    /// <summary>Creates a <see cref="T:System.Threading.Tasks.Task`1" /> that's completed successfully with the specified result.</summary>
            /// <param name="result">The result to store into the completed task. </param>
            /// <typeparam name="TResult">The type of the result returned by the task. </typeparam>
            /// <returns>The successfully completed task.</returns>
            public static Task<TResult> FromResult<TResult>(TResult result)
            {
                return new Task<TResult>(result);
            }

      备注:如果使用Task.FromResult反复调用同一参数,可考虑用一个实际的task变量,以减少垃圾回收的次数。

    3、报告进度  IProgress<T>Progress<T>

      异步操作执行的过程中,需要展示操作的进度。

      使用ProgressChanged 事件来处理进度变化,在异步方法里面使用Report 来报告进度。

     var progress = new Progress<double>();
     progress.ProgressChanged += Progress_ProgressChanged;

    4.等待一组任务完成 Task.WhenAll

    当所有任务都完成时,返回一个完成的Task

             Task task1 = Task.Delay(TimeSpan.FromSeconds(1));
                Task task2 = Task.Delay(TimeSpan.FromSeconds(2));
                Task task3 = Task.Delay(TimeSpan.FromSeconds(3));
                await Task.WhenAll(task1, task2, task3);
            Task<int> task1 = Task.FromResult(3);
                Task<int> task2 = Task.FromResult(5);
                Task<int> task3 = Task.FromResult(7);
                int[] results = await Task.WhenAll(task1, task2, task3);

    如果所有任务类型相同,并且全部完成了,Task.WhenAll返回存有每个任务执行结果的数组

    5、等待任意任务完成。Task.WhenAny

      使用Task.WhenAny方法,该参数是一批任务,当一个任务完成时,就会返回。做为返回的Task就是那个完成的任务。

      适用于对一个操作进行多个独立的尝试,只要一个尝试完成,任务就算完成。例如向多个web服务器查询天气等。

     private async Task<string> GetStringUrl(string urlA, string urlB)
            {
                var httpClient = new HttpClient();
    
                Task<string> taskA = httpClient.GetStringAsync(urlA);
                Task<string> taskB = httpClient.GetStringAsync(urlB);
                Task<string> completedTask = await Task.WhenAny(taskA, taskB);
                return await completedTask;
            }

      

  • 相关阅读:
    多重背包POJ1276不要求恰好装满 poj1014多重背包恰好装满
    哈理工1053完全背包
    求最小公倍数与最大公约数的函数
    Bus Pass ZOJ 2913 BFS 最大中取最小的
    POJ 3624 charm bracelet 01背包 不要求装满
    HavelHakimi定理(判断一个序列是否可图)
    z0j1008Gnome Tetravex
    ZOJ 1136 Multiple BFS 取模 POJ 1465
    01背包 擎天柱 恰好装满 zjut(浙江工业大学OJ) 1355
    zoj 2412 水田灌溉,求连通分支个数
  • 原文地址:https://www.cnblogs.com/tangchun/p/9145078.html
Copyright © 2011-2022 走看看