《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 的真实世界云应用程序):
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
的返回值是提供的多个任务中已完成的任务。
如果已完成的任务completedtask
和timeouttask
相等,证明最先完成的任务是等待三秒之后完成的任务timeouttask
,也就是说downloadtask
没有在三秒内完成。
上一篇: C#字符串要点(复习专用)
推荐阅读
-
《C#并发编程经典实例》学习笔记—3.1 数据的并行处理
-
《C#并发编程经典实例》学习笔记—2.1 暂停一段时间
-
《C#并发编程经典实例》读书笔记-关于并发编程的几个误解
-
《C#并发编程经典实例》学习笔记—2.2 返回完成的任务
-
《C#并发编程经典实例》学习笔记-进程(process)和线程(thread)
-
《C#并发编程经典实例》学习笔记—2.9 处理 async void 方法的异常
-
《C#并发编程经典实例》学习笔记—2.8 处理 async Task 方法的异常
-
《C#并发编程经典实例》学习笔记-第一章并发编程概述
-
《C#并发编程经典实例》学习笔记-第一章并发编程概述
-
《C#并发编程经典实例》学习笔记—2.5 等待任意一个任务完成 Task.WhenAny