C#事件反跳 [英] C# event debounce

查看:71
本文介绍了C#事件反跳的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在听硬件事件消息,但我需要对其进行反跳处理,以免查询过多.

I'm listening to a hardware event message, but I need to debounce it to avoid too many queries.

这是发送计算机状态的硬件事件,出于统计目的,我必须将其存储在数据库中,有时会发生其状态变化非常频繁(闪烁?)的情况.在这种情况下,我只想存储一个稳定"状态,我想通过将状态存储到数据库之前仅等待1-2秒来实现它.

This is an hardware event that sends the machine status and I have to store it in a database for statistical purposes, and it sometimes happens that its status changes very often (flickering?). In this case I would like to store only a "stable" status and I want to implement it by simply waiting for 1-2s before storing the status to the database.

这是我的代码:

private MachineClass connect()
{
    try
    {
        MachineClass rpc = new MachineClass();
        rpc.RxVARxH += eventRxVARxH;
        return rpc;
    }
    catch (Exception e1)
    {
        log.Error(e1.Message);
        return null;
    }
}

private void eventRxVARxH(MachineClass Machine)
{
    log.Debug("Event fired");
}

我将此行为称为反跳":请等待几次才能真正完成其工作:如果在反跳时间内再次触发了同一事件,则我必须取消第一个请求并开始等待反跳时间才能完成第二件事.

I call this behaviour "debounce": wait a few times to really do its job: if the same event is fired again during the debounce time, I have to dismiss the first request and start to wait the debounce time to complete the second event.

管理它的最佳选择是什么?只是一个计时器吗?

What is the best choice to manage it? Simply a one-shot timer?

要说明反跳"功能,请参阅以下javascript实现中的关键事件: http://benalman.com/code/projects/jquery-throttle-反跳/示例/反跳/

To explain the "debounce" function please see this javascript implementation for key events: http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/

推荐答案

由于存在一些细微差别,所以这不是一个从头开始编写代码的琐碎请求.类似的情况是监视FileSystemWatcher并等待大拷贝后安静下来,然后再尝试打开修改的文件.

This isn't a trivial request to code from scratch as there are several nuances. A similar scenario is monitoring a FileSystemWatcher and waiting for things to quiet down after a big copy, before you try to open the modified files.

.NET 4.5中的反应性扩展是为了完全处理这些情况而创建的.您可以轻松地使用它们来通过油门缓冲区窗口示例.您将事件发布到主题,对它应用一种窗口功能,例如,仅当X秒或Y事件中没有活动时才获得通知,然后订阅该通知.

Reactive Extensions in .NET 4.5 were created to handle exactly these scenarios. You can use them easily to provide such functionality with methods like Throttle, Buffer, Window or Sample. You post the events to a Subject, apply one of the windowing functions to it, for example to get a notification only if there was no activity for X seconds or Y events, then subscribe to the notification.

Subject<MyEventData> _mySubject=new Subject<MyEventData>();
....
var eventSequenc=mySubject.Throttle(TimeSpan.FromSeconds(1))
                          .Subscribe(events=>MySubscriptionMethod(events));

只有在窗口中没有其他事件的情况下,Throttle才会在滑动窗口中返回最后一个事件.任何事件都会重置窗口.

Throttle returns the last event in a sliding window, only if there were no other events in the window. Any event resets the window.

您可以在此处找到非常好的时移功能概述

您的代码收到事件后,只需使用OnNext将其发布到主题:

When your code receives the event, you only need to post it to the Subject with OnNext:

_mySubject.OnNext(MyEventData);

如果硬件事件是典型的.NET事件,则可以使用此处:

If your hardware event surfaces as a typical .NET Event, you can bypass the Subject and manual posting with Observable.FromEventPattern, as shown here:

var mySequence = Observable.FromEventPattern<MyEventData>(
    h => _myDevice.MyEvent += h,
    h => _myDevice.MyEvent -= h);  
_mySequence.Throttle(TimeSpan.FromSeconds(1))
           .Subscribe(events=>MySubscriptionMethod(events));

您还可以从Tasks中创建可观察对象,将事件序列与LINQ运算符组合起来进行请求,例如:使用Zip对成对的不同硬件事件,使用另一个事件源来绑定Throttle/Buffer等,添加延迟等等.

You can also create observables from Tasks, combine event sequences with LINQ operators to request eg: pairs of different hardware events with Zip, use another event source to bound Throttle/Buffer etc, add delays and a lot more.

Reactive Extensions可以作为 NuGet软件包提供,因此添加起来非常容易将它们添加到您的项目中.

Reactive Extensions is available as a NuGet package, so it's very easy to add them to your project.

Stephen Cleary的书" C#食谱中的并发"是非常关于Reactive Extensions的好资源,并解释了如何使用它以及如何将其与.NET中的其他并发API(如任务,事件等)配合使用.

Stephen Cleary's book "Concurrency in C# Cookbook" is a very good resource on Reactive Extensions among other things, and explains how you can use it and how it fits with the rest of the concurrent APIs in .NET like Tasks, Events etc.

Rx简介是一系列出色的文章(这是我从中复制示例的地方),以及几个示例.

Introduction to Rx is an excellent series of articles (that's where I copied the samples from), with several examples.

更新

使用您的特定示例,您可以执行以下操作:

Using your specific example, you could do something like:

IObservable<MachineClass> _myObservable;

private MachineClass connect()
{

    MachineClass rpc = new MachineClass();
   _myObservable=Observable
                 .FromEventPattern<MachineClass>(
                            h=> rpc.RxVARxH += h,
                            h=> rpc.RxVARxH -= h)
                 .Throttle(TimeSpan.FromSeconds(1));
   _myObservable.Subscribe(machine=>eventRxVARxH(machine));
    return rpc;
}

这当然可以极大地改进-可观察的和订阅都需要在某个时候进行处理.此代码假定您仅控制单个设备.如果您有许多设备,则可以在类内部创建可观察对象,以便每个MachineClass公开并处置其自己的可观察对象.

This can be improved vastly of course - both the observable and the subscription need to be disposed at some point. This code assumes that you only control a single device. If you have many devices, you could create the observable inside the class so that each MachineClass exposes and disposes its own observable.

这篇关于C#事件反跳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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