祝福所有低调善良的技术人
祝福所有低调善良的技术人
本系列学习在.NET中的并发并行编程模式,实战技巧
本小节开始学习基于任务的函数式并行。本系列保证最少代码呈现量,虽然talk is cheap, show me the code被奉为圭臬,我的学习习惯是,只学习知识点,代码不在当下立马要用的时候不会认真去读的,更何况在大多时候在手机阅读更不顺畅。
上一小节介绍了.NET中的异步支持,以及任务异步模型,异步的取消等。本小节继续介绍下异步的重试和错误处理。
异步请求有时会因为网络原因等到导致任务失败,重试也许就好了,因为对于任务可以指定次数的重试,两次尝试之间指定时间间隔。
public static async Task<T> Retry<T>(Func<Task<T>> task, int retries,TimeSpan delay, CancellationToken cts = default(CancellationToken)) =>
await task().ContinueWith(async innerTask =>
{
cts.ThrowIfCancellationRequested();
if (innerTask.Status != TaskStatus.Faulted)
return innerTask.Result;
if (retries == 0)
throw innerTask.Exception ?? throw new Exception();
await Task.Delay(delay, cts);
return await Retry(task, retries - 1, delay, cts);
}).Unwrap()
Retry异步操作,我们将此方法放在AsyncEx异步扩展静态类中。ThrowIfCancellationRequested检查下是否手动取消了,然后任务成功就返回,任务失败就延迟指定时间启动任务,递减重试次数。知道重试次数耗尽抛出异常。
下面是一个调用实例:
string stockHistory =
await AsyncEx.Retry(() => DownloadStockHistory(symbol), 5, TimeSpan.FromSeconds(2));
重试是一种错误处理机制。重试一直不行呢,就需要切换任务函数执行。使用Otherwise组合器接收两个任务,如果第一个任务失败就执行第二个任务。通过Status判断任务成功与否。
public static Task<T> Otherwise<T>(this Task<T> task, Func<Task<T>> orTask) =>
task.ContinueWith(async innerTask =>
{
if (innerTask.Status == TaskStatus.Faulted) return await orTask();
return await Task.FromResult<T>(innerTask.Result);
}).Unwrap();
调用实例如下:
Image image = await Retry(async () =>
await DownloadImageAsync("Bugghina001.jpg")
.Otherwise(async () =>
await DownloadImageAsync("Bugghina002.jpg")),
5, TimeSpan.FromSeconds(2));
上面静态方法都是在AsyncEx静态帮助类中,以获得更加牢靠的任务执行。
平常我做桌面开发和少量的web后台,用到并行的地方很少,我们体量没有那么大,一直处理单线程模式中,脑子也是单核的。并行理解确实晦涩难懂,还是应该慢慢熟练,走出安逸圈的过程必定痛苦的,现在有些许的明朗了。
前年说了很多函数组合器,下一节就重点看看这个,能给任务带来多丝滑的体验
祝福所有低调善良的技术人
简单快乐