替代使用async()=>最终在Rx中 [英] Alternative to using async () => in Rx Finally

查看:79
本文介绍了替代使用async()=>最终在Rx中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的理解是,应避免async void Action一起使用时,async () =>只是伪装的async void.

My understanding is that async void, should be avoided and that async () => is just async void in disguise when used with Action.

因此,使用 Rx.NET最终运算符应避免与async () =>异步进行,因为最终接受Action作为参数:

Hence, using the Rx.NET Finally operator asynchronously with async () => should be avoided since Finally accepts Action as parameter:

IObservable<T>.Finally(async () =>
{
    await SomeCleanUpCodeAsync();
};

但是,如果这是不好的做法,那么如果我的观察对象是OnError或OnCompleted,那么在我需要异步关闭网络coOnCompleted的情况下,什么是最佳实践?

However, if this is bad practise, what is then best practice to use in the case where I need to asynchronously close a network coOnCompleted matter if my observable is OnError or OnCompleted?

推荐答案

我的理解是,应该避免异步无效,并且async () =>只是伪装的async void.

My understanding is that async void, should be avoided and that async () => is just async void in disguise.

这是部分错误的. async () =>可以匹配Func<Task>(良好)或Action(不良).好的/不好的主要原因是async void调用中发生的异常会使进程崩溃,而async Task异常是可捕获的.

This is partially wrong. async () => can either match Func<Task> (good) or Action (bad). The main reason for good/bad is that an exception that occurs in a async void call crashes the process, whereas a async Task exception is catchable.

因此,我们只需要编写一个使用Func<Task>而不是像Observable.Finally这样的ActionAsyncFinally运算符:

So we just need to write an AsyncFinally operator that takes in a Func<Task> instead of an Action like Observable.Finally:

public static class X
{
    public static IObservable<T> AsyncFinally<T>(this IObservable<T> source, Func<Task> action)
    {
        return source
            .Materialize()
            .SelectMany(async n =>
            {
                switch (n.Kind)
                {
                    case NotificationKind.OnCompleted:
                    case NotificationKind.OnError:
                        await action();
                        return n;
                    case NotificationKind.OnNext:
                        return n;
                    default:
                        throw new NotImplementedException();
                }
            })
            .Dematerialize()
        ;
    }
}

这是用法的演示:

try
{
    Observable.Interval(TimeSpan.FromMilliseconds(100))
        .Take(10)
        .AsyncFinally(async () =>
        {
            await Task.Delay(1000);
            throw new NotImplementedException();
        })
        .Subscribe(i => Console.WriteLine(i));
}
catch(Exception e)
{
    Console.WriteLine("Exception caught, no problem");
}

如果将AsyncFinally换为Finally,则会使该过程崩溃.

If you swap out AsyncFinally for Finally, you'll crash the process.

这篇关于替代使用async()=&gt;最终在Rx中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆