Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.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#_System.reactive - Fatal编程技术网

C# 触发第一个事件后数秒的RX缓冲区事件

C# 触发第一个事件后数秒的RX缓冲区事件,c#,system.reactive,C#,System.reactive,我有一个filewatcher,可以从中观察创建和更改的事件。 我希望在触发(创建或更改)第一个事件时,它需要开始缓冲10秒,在这10秒之后,我希望处理缓冲的事件 我已经得到的是: Observable.FromEventPattern<FileSystemEventArgs>(FileSystemWatcher, "Created") .Merge(Observable.FromEventPattern<FileSystemEventArgs&

我有一个filewatcher,可以从中观察创建和更改的事件。 我希望在触发(创建或更改)第一个事件时,它需要开始缓冲10秒,在这10秒之后,我希望处理缓冲的事件

我已经得到的是:

Observable.FromEventPattern<FileSystemEventArgs>(FileSystemWatcher, "Created")
                .Merge(Observable.FromEventPattern<FileSystemEventArgs>(FileSystemWatcher, "Changed"))
                .Buffer(TimeSpan.FromSeconds(10))
                .Subscribe(list =>
                {
                   Debug.WriteLine("Do something");
                });
Observable.FromEventPattern(FileSystemWatcher,“已创建”)
.Merge(可观察的.FromEventPattern(FileSystemWatcher,“已更改”))
.缓冲区(时间跨度从秒(10))
.订阅(列表=>
{
Debug.WriteLine(“做某事”);
});
此代码执行“Debug.WriteLine(“Do something”);”每10秒

编辑: 好吧,让我试着用时间线来解释一下

  • 文件监视程序处于空闲状态,不会触发任何事件
  • 在未知时间段后,文件将被放置在目录中
  • 将触发创建的事件
  • 可观察列表开始缓冲(所有事件)10秒
  • 在这10秒钟之后,subscribe操作被执行,它将立即处理所有事件

  • 希望这能让事情变得清楚

    我假设您想要以下行为:

  • 初始事件发生后,将所有事件缓冲10秒钟
  • 一旦该10秒窗口关闭,下一个窗口应为10秒后的所有事件触发一个新的10秒缓冲区
  • 假设我们有5个项目在5秒内均匀分布,间隔13秒,然后还有5个项目在5秒内均匀分布。大理石图如下所示:

    timeline: 0--1--2--3--4--5--6--7--8--9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27
    events  : x--x--x--x--x-------------------------------------x--x--x--x--x------------------
    stdbuff : |----------------------------|-----------------------------|---------------------
    desired : BeginCapture-----------------Return---------------BeginCapture------------------Return
    
     var primaryEvents = initialSource
            .Scan(DateTimeOffset.MinValue, (lastPrimary, _) => DateTimeOffset.Now - lastPrimary > TimeSpan.FromSeconds(10) ? DateTimeOffset.Now : lastPrimary)
            .DistinctUntilChanged();
    
    使用直接
    Buffer
    的问题在于,它看起来像上面标注的
    stdbuff
    ,并将第二组事件分成两组,从而为第二组事件生成两个列表:一个包含三个事件,一个包含两个事件。您需要一个列表(用于第二个组),使用类似于
    所需
    流的逻辑。从0开始捕获,从10返回列表。17点开始抓拍,27点返回列表

    如果我(再次)误解了你,请张贴一个大理石图,类似于上面,代表你希望事情如何运作


    假设我理解正确,下面的代码将工作

    //var initialSource = Observable.FromEventPattern<FileSystemEventArgs>(fileWatcher, nameof(FileSystemWatcher.Created))
    //  .Merge(Observable.FromEventPattern<FileSystemEventArgs>(fileWatcher, nameof(FileSystemWatcher.Changed)));
    
        //Comment this out, and use the above lines for your code. This just makes testing the Rx components much easier.
    var initialSource = Observable.Interval(TimeSpan.FromSeconds(1)).Take(5)
        .Concat(Observable.Empty<long>().Delay(TimeSpan.FromSeconds(13)))
        .Concat(Observable.Interval(TimeSpan.FromSeconds(1)).Take(5));
    
    initialSource
        .Publish( _source => _source 
            .Buffer(_source
                .Scan(DateTimeOffset.MinValue, (lastPrimary, _) => DateTimeOffset.Now - lastPrimary > TimeSpan.FromSeconds(10) ? DateTimeOffset.Now : lastPrimary)
                .DistinctUntilChanged()
                .Delay(TimeSpan.FromSeconds(10))
            )
        )
        .Subscribe(list =>
        {
            Debug.WriteLine($"Time-stamp: {DateTime.Now.ToLongTimeString()}");
            Debug.WriteLine($"List Count: {list.Count}");
        });
    
    一旦我们有了可以表示窗口打开的
    BeginCapture
    事件,就很容易找到
    Return
    事件或窗口关闭:

     var closeEvents = primaryEvents.Delay(TimeSpan.FromSeconds(10));
    
    实际上,由于我们关心的收盘和开盘之间没有发生任何事情,因此我们只需要担心收盘事件,因此我们可以将其缩小为:

     var closeEvents = initialSource
            .Scan(DateTimeOffset.MinValue, (lastPrimary, _) => DateTimeOffset.Now - lastPrimary > TimeSpan.FromSeconds(10) ? DateTimeOffset.Now : lastPrimary)
            .DistinctUntilChanged()
            .Delay(TimeSpan.FromSeconds(10));
    
    将其插入
    Buffer
    ,其中
    closeEvents
    bufferbounders

    var bufferredLists = initialSource
        .Buffer(initialsource
            .Scan(DateTimeOffset.MinValue, (lastPrimary, _) => DateTimeOffset.Now - lastPrimary > TimeSpan.FromSeconds(10) ? DateTimeOffset.Now : lastPrimary)
            .DistinctUntilChanged()
            .Delay(TimeSpan.FromSeconds(10))
        );
    

    最后,由于我们有多个对
    initialSource
    的订阅,我们希望使用
    Publish
    来确保并发正常工作,从而得到最终答案。

    我假设您需要以下行为:

  • 初始事件发生后,将所有事件缓冲10秒钟
  • 一旦该10秒窗口关闭,下一个窗口应为10秒后的所有事件触发一个新的10秒缓冲区
  • 假设我们有5个项目在5秒内均匀分布,间隔13秒,然后还有5个项目在5秒内均匀分布。大理石图如下所示:

    timeline: 0--1--2--3--4--5--6--7--8--9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27
    events  : x--x--x--x--x-------------------------------------x--x--x--x--x------------------
    stdbuff : |----------------------------|-----------------------------|---------------------
    desired : BeginCapture-----------------Return---------------BeginCapture------------------Return
    
     var primaryEvents = initialSource
            .Scan(DateTimeOffset.MinValue, (lastPrimary, _) => DateTimeOffset.Now - lastPrimary > TimeSpan.FromSeconds(10) ? DateTimeOffset.Now : lastPrimary)
            .DistinctUntilChanged();
    
    使用直接
    Buffer
    的问题在于,它看起来像上面标注的
    stdbuff
    ,并将第二组事件分成两组,从而为第二组事件生成两个列表:一个包含三个事件,一个包含两个事件。您需要一个列表(用于第二个组),使用类似于
    所需
    流的逻辑。从0开始捕获,从10返回列表。17点开始抓拍,27点返回列表

    如果我(再次)误解了你,请张贴一个大理石图,类似于上面,代表你希望事情如何运作


    假设我理解正确,下面的代码将工作

    //var initialSource = Observable.FromEventPattern<FileSystemEventArgs>(fileWatcher, nameof(FileSystemWatcher.Created))
    //  .Merge(Observable.FromEventPattern<FileSystemEventArgs>(fileWatcher, nameof(FileSystemWatcher.Changed)));
    
        //Comment this out, and use the above lines for your code. This just makes testing the Rx components much easier.
    var initialSource = Observable.Interval(TimeSpan.FromSeconds(1)).Take(5)
        .Concat(Observable.Empty<long>().Delay(TimeSpan.FromSeconds(13)))
        .Concat(Observable.Interval(TimeSpan.FromSeconds(1)).Take(5));
    
    initialSource
        .Publish( _source => _source 
            .Buffer(_source
                .Scan(DateTimeOffset.MinValue, (lastPrimary, _) => DateTimeOffset.Now - lastPrimary > TimeSpan.FromSeconds(10) ? DateTimeOffset.Now : lastPrimary)
                .DistinctUntilChanged()
                .Delay(TimeSpan.FromSeconds(10))
            )
        )
        .Subscribe(list =>
        {
            Debug.WriteLine($"Time-stamp: {DateTime.Now.ToLongTimeString()}");
            Debug.WriteLine($"List Count: {list.Count}");
        });
    
    一旦我们有了可以表示窗口打开的
    BeginCapture
    事件,就很容易找到
    Return
    事件或窗口关闭:

     var closeEvents = primaryEvents.Delay(TimeSpan.FromSeconds(10));
    
    实际上,由于我们关心的收盘和开盘之间没有发生任何事情,因此我们只需要担心收盘事件,因此我们可以将其缩小为:

     var closeEvents = initialSource
            .Scan(DateTimeOffset.MinValue, (lastPrimary, _) => DateTimeOffset.Now - lastPrimary > TimeSpan.FromSeconds(10) ? DateTimeOffset.Now : lastPrimary)
            .DistinctUntilChanged()
            .Delay(TimeSpan.FromSeconds(10));
    
    将其插入
    Buffer
    ,其中
    closeEvents
    bufferbounders

    var bufferredLists = initialSource
        .Buffer(initialsource
            .Scan(DateTimeOffset.MinValue, (lastPrimary, _) => DateTimeOffset.Now - lastPrimary > TimeSpan.FromSeconds(10) ? DateTimeOffset.Now : lastPrimary)
            .DistinctUntilChanged()
            .Delay(TimeSpan.FromSeconds(10))
        );
    

    最后,由于我们有多个订阅
    initialSource
    ,我们希望使用
    Publish
    来确保并发正常工作,从而得出最终答案。

    您当前的代码有什么问题?您为什么不使用
    列表
    ?或者你想单独处理列表中的每一项?你只想触发一次还是什么?听起来你的解决方案是合适的。附带说明:你应该保留一个订阅的引用,当你对这些事件不再感兴趣时将其处理掉。如果您不处置订阅并且它超出范围,那么它可能仍然保留对事件的强引用(并可能导致泄漏)。请相应地编辑答案。您当前的代码有什么问题?您为什么不使用
    列表
    ?或者你想单独处理列表中的每一项?你只想触发一次还是什么?听起来你的解决方案是合适的。附带说明:你应该保留一个订阅的引用,当你对这些事件不再感兴趣时将其处理掉。如果您不处理订阅并且它超出了范围,那么它可能仍然保留对事件的强引用(并可能导致泄漏)。相应地编辑了答案。请为您期望它如何工作写一个时间表。这确实有效。我想会有一个更简单的解决办法。有点