• 《C#并发编程经典实例》学习笔记—2.1 暂停一段时间


    问题:

    需要让程序(以异步方式)等待一段时间。

    解决方案:Task类的静态函数Delay,返回Task对象

    在github开源项目dotnet/coreclr,找到Task.cs有关Delay方法的源码
    github地址:
    https://github.com/dotnet/coreclr/blob/master/src/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs

            /// <summary>
            /// Creates a Task that will complete after a time delay.
            /// </summary>
            /// <param name="millisecondsDelay">The number of milliseconds to wait before completing the returned Task</param>
            /// <returns>A Task that represents the time delay</returns>
            /// <exception cref="T:System.ArgumentOutOfRangeException">
            /// The <paramref name="millisecondsDelay"/> is less than -1.
            /// </exception>
            /// <remarks>
            /// After the specified time delay, the Task is completed in RanToCompletion state.
            /// </remarks>
            public static Task Delay(int millisecondsDelay)
            {
                return Delay(millisecondsDelay, default);
            }
    

    Delay方法会创建一个延迟millisecondsDelay 毫秒后完成的任务。
    millisecondsDelay 为 在完成返回的任务前要等待的毫秒数,如果值为-1,将无限期等待。

    Delay方法有多个重载方法,如下

    public static Task Delay(TimeSpan delay);
    public static Task Delay(TimeSpan delay, CancellationToken cancellationToken);
    public static Task Delay(int millisecondsDelay);
    public static Task Delay(int millisecondsDelay, CancellationToken cancellationToken);
    

    书中给出三个例子。
    一个是单元测试中,定义一个异步完成的任务,以完成“异步成功”测试。

    static async Task<T> DelayResult<T>(T result, TimeSpan delay)
    {
    	await Task.Delay(delay);
    	return result;
    }
    

    一个是指数退避的简单实现

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

    书中提到实际产品开发中,应对指数退避重试机制有更周密的解决方案。书中推荐了微软企业库中的瞬间错误处理模块(Transient Error Handling Block),在微软Docs中找到了相关文章。
    暂时性故障处理 (构建使用 Azure 的真实世界云应用程序):
    https://docs.microsoft.com/zh-cn/aspnet/aspnet/overview/developing-apps-with-windows-azure/building-real-world-cloud-apps-with-windows-azure/transient-fault-handling

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

    上述代码实现的是对异步get请求进行多次重试。

    最后一个例子,是实现了一个简单的超时功能,当get请求在3秒内没有响应,返回null。

    		static async Task<string> DownloadStringWithTimeout(string uri)
            {
                using (var client = new HttpClient())
                {
                    var downloadTask = client.GetStringAsync(uri);
                    var timeoutTask = Task.Delay(3000);
                    var completedTask = await Task.WhenAny(downloadTask, timeoutTask);
                    if (completedTask == timeoutTask)
                        return null;
                    return await downloadTask;
                }
            }
    

    该代码的实现主要是借助于Task.WhenAny方法。
    Task.WhenAny的返回值是提供的多个任务中已完成的任务。
    如果已完成的任务completedTasktimeoutTask相等,证明最先完成的任务是等待三秒之后完成的任务timeoutTask,也就是说downloadTask 没有在三秒内完成。

  • 相关阅读:
    C# 空合并运算符 ??
    基于ASP.NET Core 创建 Web API
    使用 csc.exe 编译C#代码
    NPOI创建Excel批注
    http协议 put、delete请求asp.net mvc应用,报404错误
    visual studio清理nuget包缓存
    String.IsNullOrEmpty 与 String.IsNullOrWhiteSpace
    C# linq to xml 简单示例
    SQL Server修改表结构,不允许保存更改。
    SQL Server 分离与附加数据库
  • 原文地址:https://www.cnblogs.com/AlienXu/p/9562547.html
Copyright © 2020-2023  润新知