异步编程基础

  本质上适合异步的操作有: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;
        }

 

  

posted @ 2018-06-06 14:49  _York  阅读(352)  评论(0编辑  收藏  举报