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;
            }

      

  • 相关阅读:
    谈谈.Net中的协变和逆变(转)
    如何转移 mysql 数据库,更换服务器之后mysql如何还原
    华盾服务器管理专家,WEB后台密码忘记了,恢复默认初始密码
    合理设置应用程序池 保证网站合理运行
    2012年4月QQ企业邮箱收费后最新版图文教程开通QQ企业邮箱
    word的加密
    在IE下FLASH背景透明而在FF下不透明的解决方法
    当重装数系统/数据库之后,如何恢复数据库的账号 登录名/用户名 孤立用户 缩小ldf日志文件 修改sqlserver2000端口
    ISAPI_Rewrite的安装配置以及加载未知的原因/和无法使用的原因
    网站建设的功能模块说明
  • 原文地址:https://www.cnblogs.com/tangchun/p/9145078.html
Copyright © 2011-2022 走看看