问题:

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

解决方案: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#并发编程经典实例》学习笔记—2.1 暂停一段时间的更多相关文章

  1. 《C#并发编程经典实例》笔记

    1.前言 2.开宗明义 3.开发原则和要点 (1)并发编程概述 (2)异步编程基础 (3)并行开发的基础 (4)测试技巧 (5)集合 (6)函数式OOP (7)同步 1.前言 最近趁着项目的一段平稳期 ...

  2. 《C#并发编程经典实例》学习笔记—2.7 避免上下文延续

    避免上下文延续 在默认情况下,一个 async 方法在被 await 调用后恢复运行时,会在原来的上下文中运行. 为了避免在上下文中恢复运行,可让 await 调用 ConfigureAwait 方法 ...

  3. 《C#并发编程经典实例》学习笔记—3.1 数据的并行处理

    问题 有一批数据,需要对每个元素进行相同的操作.该操作是计算密集型的,需要耗费一定的时间. 解决方案 常见的操作可以粗略分为 计算密集型操作 和 IO密集型操作.计算密集型操作主要是依赖于CPU计算, ...

  4. 《C#并发编程经典实例》学习笔记—2.3 报告任务

    问题 异步操作时,需要展示该操作的进度 解决方案 IProgress<T> Interface和Progress<T> Class 插一段话:读<C#并发编程经典实例&g ...

  5. 《C# 并发编程 · 经典实例》读书笔记

    前言 最近在看<C# 并发编程 · 经典实例>这本书,这不是一本理论书,反而这是一本主要讲述怎么样更好的使用好目前 C#.NET 为我们提供的这些 API 的一本书,书中绝大部分是一些实例 ...

  6. [书籍]用UWP复习《C#并发编程经典实例》

    1. 简介 C#并发编程经典实例 是一本关于使用C#进行并发编程的入门参考书,使用"问题-解决方案-讨论"的模式讲解了以下这些概念: 面向异步编程的async和await 使用TP ...

  7. 《C#并发编程经典实例》学习笔记-关于并发编程的几个误解

    误解一:并发就是多线程 实际上多线程只是并发编程的一种形式,在C#中还有很多更实用.更方便的并发编程技术,包括异步编程.并行编程.TPL 数据流.响应式编程等. 误解二:只有大型服务器程序才需要考虑并 ...

  8. 《C#并发编程经典实例》学习笔记-第一章并发编程概述

    并发编程的术语 并发 同时做多件事情 多线程 并发的一种形式,它采用多个线程来执行程序. 多线程是并发的一种形式,但不是唯一的形式. 并行处理 把正在执行的大量的任务分割成小块,分配给多个同时运行的线 ...

  9. 并发编程概述--C#并发编程经典实例

    优秀软件的一个关键特征就是具有并发性.过去的几十年,我们可以进行并发编程,但是难度很大.以前,并发性软件的编写.调试和维护都很难,这导致很多开发人员为图省事放弃了并发编程.新版.NET 中的程序库和语 ...

随机推荐

  1. U-Boot Makefile分析(1)配置脚本mkconfig分析

    我们在编译U-Boot之前,需要根据当前使用的板子进行配置,例如make s5p_goni_config,接着才能进行编译make.下面首先分析配置阶段U-Boot做了哪些事情. 由于执行这些命令是在 ...

  2. Exception.ToString()使用及其他方法比较

    在日常C#的编码过程中,我们常常会使用try...catch...来抓住代码异常,并且在异常的时候打印log, 如下 try { } catch (Exception e) { //输出Log信息等 ...

  3. 使用koa2+es6/7打造高质量Restful API

    前言 如今nodejs变得越来越火热,采用nodejs实现前后端分离架构已被多数大公司所采用. 在过去,使用nodejs大家首先想到的是TJ大神写的express.js,而发展到如今,更轻量,性能更好 ...

  4. 两台Linux机器传送文件

    https://www.cnblogs.com/lianrenjujishou/p/5458206.html

  5. Android逆向之smali学习

    Smali是Android虚拟机Dalvik反汇编的结果. Dalvik指令集 指令格式为:[op]-[type](可选)/[位宽,默认4位] [目标寄存器],[源寄存器](可选) 赋值:move*  ...

  6. 关于 this 关键字的使用

    package com.jsti.guiyang_01; /* 自定义Phone类 this关键字 代表当前正在调用这个方法(访问成员变量)的对象(实例) 1.在setxxx方法中用来区分成员变量和局 ...

  7. HDFS-HA高可用

    HDFS-HA工作机制 通过双NameNode消除单点故障 HDFS-HA工作要点 1.元数据管理方式需要改变 内存中各自保存一份元数据: Edits日志只有Active状态的NameNode节点可以 ...

  8. Python自动化编程-树莓派的介绍与使用(一)

    Raspberry Pi(中文名为“树莓派”,简写为RPi,(或者RasPi / RPI) [1]  是为学习计算机编程教育而设计),只有信用卡大小的微型电脑,其系统基于Linux.  随着Windo ...

  9. 每天学点SpringCloud(五):如何使用高可用的Eureka

    前几篇文章我们讲了一下Eureka的基础使用,但是呢有一个很重要的问题,我们讲的都是单机版的情况,如果这个时候Eureka服务挂了的话,那么我们的服务提供者跟服务消费者岂不是都废了?服务提供者和消费者 ...

  10. 第69节:Java中数据库的多表操作

    第69节:Java中数据库的多表操作 前言 学习数据库的多表操作,去电商行业做项目吧!!! 达叔,理工男,简书作者&全栈工程师,感性理性兼备的写作者,个人独立开发者,我相信你也可以!阅读他的文 ...