.NET并发编程-异步编程模型下

本系列学习在.NET中的并发并行编程模式,实战技巧

内容目录

1、异步重试2、错误处理3、再说一句

本小节开始学习基于任务的函数式并行。本系列保证最少代码呈现量,虽然talk is cheap, show me the code被奉为圭臬,我的学习习惯是,只学习知识点,代码不在当下立马要用的时候不会认真去读的,更何况在大多时候在手机阅读更不顺畅。

上一小节介绍了.NET中的异步支持,以及任务异步模型,异步的取消等。本小节继续介绍下异步的重试和错误处理。

1、异步重试

异步请求有时会因为网络原因等到导致任务失败,重试也许就好了,因为对于任务可以指定次数的重试,两次尝试之间指定时间间隔。

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

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静态帮助类中,以获得更加牢靠的任务执行。

3、再说一句

平常我做桌面开发和少量的web后台,用到并行的地方很少,我们体量没有那么大,一直处理单线程模式中,脑子也是单核的。并行理解确实晦涩难懂,还是应该慢慢熟练,走出安逸圈的过程必定痛苦的,现在有些许的明朗了。

前面说了很多函数组合器,下一节就重点看看这个,能给任务带来多丝滑的体验

写给普通:
祝福所有低调善良的技术人
简单快乐

to be contiued!
下集:函数组合器

posted @ 2021-04-01 09:45  那是山  阅读(38)  评论(0编辑  收藏  举报