Это не тривиальная просьба писать код с нуля, так как есть несколько нюансов. Аналогичный сценарий отслеживает FileSystemWatcher и ждет, пока все успокоится после большой копии, прежде чем пытаться открыть измененные файлы.
Реактивные расширения в .NET 4.5 были созданы именно для таких сценариев. Вы можете легко использовать их для обеспечения такой функциональности с помощью таких методов, как Дроссель, Буфер, Окно или пример . Вы публикуете события в Subject , применить к нему одну из оконных функций, например, чтобы получать уведомление, только если не было активности в течение X секунд или Y событий, затем подпишитесь на уведомление.
Subject<MyEventData> _mySubject=new Subject<MyEventData>();
....
var eventSequenc=mySubject.Throttle(TimeSpan.FromSeconds(1))
.Subscribe(events=>MySubscriptionMethod(events));
Throttle возвращает последнее событие в скользящем окне, только если в окне не было других событий. Любое событие сбрасывает окно.
Очень хороший обзор функций со сдвигом во времени можно найти здесь а>
Когда ваш код получает событие, вам нужно только опубликовать его в теме с помощью OnNext:
_mySubject.OnNext(MyEventData);
Если ваше аппаратное событие отображается как типичное событие .NET, вы можете обойти тему и ручную публикацию с помощью Observable.FromEventPattern, как показано здесь:
var mySequence = Observable.FromEventPattern<MyEventData>(
h => _myDevice.MyEvent += h,
h => _myDevice.MyEvent -= h);
_mySequence.Throttle(TimeSpan.FromSeconds(1))
.Subscribe(events=>MySubscriptionMethod(events));
Вы также можете создавать наблюдаемые из задач, комбинировать последовательности событий с операторами LINQ для запроса, например: пары различных аппаратных событий с Zip, использовать другой источник событий для привязки Throttle/Buffer и т. д., добавлять задержки и многое другое.
Реактивные расширения доступны в виде пакета NuGet, поэтому их очень легко добавить в ваш проект.
Книга Стивена Клири Параллелизм в C# Cookbook очень хороша. ресурс по реактивным расширениям, среди прочего, и объясняет, как вы можете его использовать и как он сочетается с остальными параллельными API в .NET, такими как задачи, события и т. д.
Введение в Rx – это отличная серия статей ( оттуда я скопировал образцы), с несколькими примерами.
ОБНОВЛЕНИЕ
Используя ваш конкретный пример, вы можете сделать что-то вроде:
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 выставлял и удалял свое собственное наблюдаемое.
12.02.2015