Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.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# Rx延迟控制器扩展实现_C#_Extension Methods_System.reactive - Fatal编程技术网

C# Rx延迟控制器扩展实现

C# Rx延迟控制器扩展实现,c#,extension-methods,system.reactive,C#,Extension Methods,System.reactive,我正在尝试在C#中实现bool值的扩展。实现应该直接传递假值,但当接收到真值时,它应该延迟输出带有前缀延迟的真值 大理石图应为: |Delay| |Delay| F---T---F---T----T---T---F---C -F-----------------T------F---C 注: 它应该包含不同的值(或不包含) 仅当源中的真值至少延迟了一段时间时,它才应输出真值 如果输出中有一组真值,则使用第一个值计算延迟 当源发出false时,应立即传递到输出 我目前的实

我正在尝试在C#中实现bool值的扩展。实现应该直接传递假值,但当接收到真值时,它应该延迟输出带有前缀延迟的真值

大理石图应为:

      |Delay| |Delay|
  F---T---F---T----T---T---F---C
  -F-----------------T------F---C
注:

  • 它应该包含不同的值(或不包含)
  • 仅当源中的真值至少延迟了一段时间时,它才应输出真值
  • 如果输出中有一组真值,则使用第一个值计算延迟
  • 当源发出false时,应立即传递到输出
我目前的实现是

公共静态IObservable ThrottleOnTrue(此IObservable源,时间跨度延迟)
{
返回source.DistinctUntilChanged()。选择(值=>value
?可观察的。从不()。开始(真)。延迟(延迟)
:可观察。从不().StartWith(false))
.开关();
}
但似乎不起作用,因为之后的真值没有正确地取消,之后的假值。我是Rx的新手,所以可能有更好的方法来实现这个扩展


这将用于检查多个服务器应用程序的IObservable CanProcessMoreJobs属性,在快速输出更改后,只向服务器添加更多作业,且至少具有延迟值的真值。

这是一个有趣的问题,我确实想知道这是否可能是一种问题。无论如何,考虑到您的大理石图,您几乎肯定不需要一个
DistinctUntilChanged()
,否则您将永远不会得到重复的“F”

我的方法(当然还有其他方法)是安排所需的输出,确保删除任何“节流”的值(即在延迟期内T后跟F)。这可以通过以下方式实现:

public static IObservable<bool> ThrottleOnTrue(this IObservable<bool> source, TimeSpan delay) =>
    source
        .Select(value =>
            Observable
                .Return(value)
                .Delay(value ? delay : TimeSpan.Zero))
        .Switch();
public static IObservable ThrottleOnTrue(此IObservable源、TimeSpan延迟、isScheduler调度程序)
{
返回可观察的。创建(
观察员=>
{
var serialDisposable=新的serialDisposable();
var延迟=源
.具体化
.扫描(
(通知:(通知)无效,延迟:0L),
(种子,源)=>source.Kind开关
{
NotificationKind.OnCompleted=>(Notification.CreateOnCompleted(),seed.Delay),
NotificationKind.OneError=>(Notification.createOneError(source.Exception),0),
_=>source.Value
?(Notification.CreateOnNext(source.Value),delay.Ticks+1)
:(Notification.CreateOnNext(source.Value),1)
})
.Where(tuple=>tuple.Notification!=null)
.Publish();
//在延迟后发出值,取消受限制的项
var onNext=延迟
.Where(tuple=>tuple.Notification.Kind==NotificationKind.OnNext)
.Subscribe(tuple=>serialDisposable.Disposable=scheduler.Schedule(scheduler.Now.AddTicks(tuple.Delay),()=>observer.OnNext(tuple.Notification.Value));
//在最后一个要发射的项目延迟后发射完成
var onCompleted=延迟
.Where(tuple=>tuple.Notification.Kind==NotificationKind.OnCompleted)
.Subscribe(tuple=>scheduler.Schedule(scheduler.Now.AddTicks(tuple.Delay),()=>observer.OnCompleted());
//立即发出错误,取消所有挂起的项
var onError=延迟
.Where(tuple=>tuple.Notification.Kind==NotificationKind.OnError)
.Subscribe(tuple=>serialDisposable.Disposable=scheduler.Schedule(TimeSpan.Zero,()=>observer.OnError(tuple.Notification.Exception));
返回新的CompositeDisposable(新的IDisposable[]{onNext,onCompleted,onError,delays.Connect(),serialDisposable});
}
);
}
它看起来有点复杂,因为需要在之前延迟的项(我们使用
Scan
tuple跟踪)之后处理完成

无论如何,请注意添加了
调度程序
参数。在向Rx添加任何形式的异步时,应始终提供一个参数,但可以默认设置为
调度程序。默认设置为
,如下所示:

公共静态IObservable ThrottleOnTrue(此IObservable源,时间跨度延迟)
{
返回source.ThrottleOnTrue(delay,Scheduler.Default);
}
现在,ThrottleOnTrue可以通过使用的“虚拟时间”显示工作(使用稍微不同的大理石图)。这里有一个测试显示“F”值会立即发出(当前时间+1勾用于调度):

private static long SchedulerOffset=ReactiveTest.Created+ReactiveTest.Subscribed;
私有静态长通知偏移量=ReactiveTest.Subscribed;
/// 
///来源:F--F--F-C
///预期:-F---F---F-C
/// 
[测试]
public void应直接传递FalseValues()
{
var scheduler=newtestscheduler();
var source=new[]
{
新录制的(TimeSpan.FromSeconds(1).Ticks,Notification.CreateOnNext(false)),
新录制的(TimeSpan.FromSeconds(2).Ticks,Notification.CreateOnNext(false)),
新录制的(TimeSpan.FromSeconds(3).Ticks,Notification.CreateOnNext(false)),
新录制(TimeSpan.FromSeconds(3).Ticks+1,Notification.CreateOnCompleted())
};
预期风险值=新[]
{
新录制的(TimeSpan.FromSeconds(1).Ticks+NotificationOffset+1,Notification.CreateOnNext(false)),
新录制的(TimeSpan.FromSeconds(2).Ticks+NotificationOffset+1,Notification.CreateOnNext(false)),
新录制的(TimeSpan.FromSeconds(3).Ticks+NotificationOffset+1,Notification.CreateOnNext(false)),
新录制(时间跨度从秒(3)开始)。滴答声
2020/06/15 01:16:23 +00:00 False 
2020/06/15 01:16:31 +00:00 False 
2020/06/15 01:16:40 +00:00 True 
2020/06/15 01:16:48 +00:00 False
public static IObservable<bool> ThrottleOnTrue(this IObservable<bool> source, TimeSpan delay) =>
    source
        .Select(value =>
            Observable
                .Return(value)
                .Delay(value ? delay : TimeSpan.Zero))
        .Switch();