Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# RetryWhen和异常逻辑_C#_Exception Handling_System.reactive - Fatal编程技术网

C# RetryWhen和异常逻辑

C# RetryWhen和异常逻辑,c#,exception-handling,system.reactive,C#,Exception Handling,System.reactive,我一直在考虑为一个简单的网络流实现一个基本的重试逻辑。其思想是有三种类型的异常需要处理: 暂时异常,应重新连接并重试 永久性错误连接,应该传播并让进程消亡 应接受的例外情况,并应完成可观察的 当我画这个草图的时候,我最终得到了 var retriedObservable = observable.RetryWhen(x => x.SelectMany(ex => { if (ex is ShouldCompleteException) { retu

我一直在考虑为一个简单的网络流实现一个基本的重试逻辑。其思想是有三种类型的异常需要处理:

  • 暂时异常,应重新连接并重试
  • 永久性错误连接,应该传播并让进程消亡
  • 应接受的例外情况,并应完成可观察的
当我画这个草图的时候,我最终得到了

var retriedObservable = observable.RetryWhen(x => x.SelectMany(ex =>
{
    if (ex is ShouldCompleteException)
    {
        return Observable.Return<Exception>(null);
    }
    else if (ex is TransientNetworkException)
    {
        return Observable.Return(ex).Delay(TimeSpan.FromSeconds(1));
    }
    else
    {
        return Observable.Throw<Exception>(ex);
    }
}).TakeUntil(ex => ex == null));
var retriedObservable=observable.RetryWhen(x=>x.SelectMany(ex=>
{
如果(ex为ShouldCompleteException)
{
返回可观察。返回(空);
}
else if(ex为TransientNetworkException)
{
返回可观测。返回(ex)。延迟(TimeSpan.FromSeconds(1));
}
其他的
{
可观测的返回距离(ex);
}
}).TakeUntil(ex=>ex==null));
Edit:这个示例非常简化,只显示了我在代码中看到的三种典型错误处理模式。在现实世界中,当然还有很多事情要做。

代码可以工作,但看起来过于复杂,我不确定这个特殊的“null”值是否会在某个时候击中我的脸

我还尝试了
.Where()
.Merge()
的组合,但是代码很快就变得不可读了


是否有一种更干净的方法(即更规范的方法)来完成这个基本的错误处理?

已经有很多这样的库了,比如。但是,如果你想实现你自己的,你可以做如下的事情

您可以创建一个
RetryPolicyHandler
类。此外,如果需要,还可以使用接口对其进行抽象,并与任何IoC容器一起使用。使用以下实现添加类似于
RetryExecuteAsync
的方法

public async Task RetryExecuteAsync(Func<Task> action)
{
    int retryCount = default(int);
    int maxNumberOfRetries = 5; // Or get from settings

    while (true)
    {
        try
        {
            await action().ConfigureAwait(false);

            break;
        }
        catch (ArgumentNullException)
        {
            // Something specific about this exception
            if (++retryCount > maxNumberOfRetries)
                throw;
        }
        catch (Exception)
        { 
            if (++retryCount > maxNumberOfRetries)
                throw;
        }
    }
}
如果需要,还可以创建其他特定方法。例如,
executedLockRetryAsync
带有捕捉
SqlException
ExecuteHttpCallRetryAsync
以处理
HttpRequestException
并以另一种方式处理它们。

这有点帮助:

var retriedObservable2 = observable.RetryWhen(exStream => Observable.Merge(
    exStream.OfType<ShouldCompleteException>().Select(_ => (Exception)null),
    exStream.NotOfType(typeof(ShouldCompleteException)).OfType<TransientNetworkException>().Delay(TimeSpan.FromSeconds(1)),
    exStream.NotOfTypes(typeof(ShouldCompleteException), typeof(TransientNetworkException)).SelectMany(e => Observable.Throw<Exception>(e))
).TakeUntil(ex => ex == null));
var retriedObservable2=observable.RetryWhen(exStream=>observable.Merge(
exStream.OfType().Select(=>(异常)null),
type()的exStream.NotOfType(typeof(ShouldCompleteException)).Delay(TimeSpan.FromSeconds(1)),
exStream.NotOfTypes(typeof(ShouldCompleteException)、typeof(TransientNetworkException))。选择many(e=>Observable.Throw(e))
).TakeUntil(ex=>ex==null));
它使用以下扩展消息:

public static class X
{
    public static IObservable<TSource> NotOfType<TSource>(this IObservable<TSource> source, Type t)
    {
        return source.Where(o => !t.IsInstanceOfType(o));
    }

    public static IObservable<TSource> NotOfTypes<TSource>(this IObservable<TSource> source, params Type[] ts)
    {
        return source.Where(o => ts.All(t => !t.IsInstanceOfType(o)));
    }
}
公共静态类X
{
公共静态IObservable NotOfType(此IObservable源,类型t)
{
返回source.Where(o=>!t.IsInstanceOfType(o));
}
公共静态IObservable NotOfTypes(此IObservable源,参数类型[]ts)
{
返回source.Where(o=>ts.All(t=>!t.IsInstanceOfType(o));
}
}

感谢链接到Polly,看起来很有用!但即使给定一个库,也必须在Rx中实现这一点。我更感兴趣的是如何在Rx中具体做到这一点,而不是它的良好实现。
public static class X
{
    public static IObservable<TSource> NotOfType<TSource>(this IObservable<TSource> source, Type t)
    {
        return source.Where(o => !t.IsInstanceOfType(o));
    }

    public static IObservable<TSource> NotOfTypes<TSource>(this IObservable<TSource> source, params Type[] ts)
    {
        return source.Where(o => ts.All(t => !t.IsInstanceOfType(o)));
    }
}