Some nonsense
In doing a synchronization device reporting by FileSystemWatcher
the report generated by the monitoring device at the specified location, parse and upload.
The reason why the monitor file system, rather than a direct connection with the device software, and there will be a large section of complaint, put aside.
While monitoring file, modify events such as file creation, sometimes several times to report, this could be a file system or implementation code related, so do anti-shake.
Before the adoption of self-defined private fields / timer done anti-shake, some trouble, but not very easy to maintain, learned online Reactive Extension
(corresponding to .net core
the System.Reactive
package), image stabilization can be done, I looked for a moment to read the relevant documents.
Beginning to look confused, the main function is too much, is not the main purpose of stabilization, it is not easy to find the content (simple and straightforward example) want
text
Observable
Created from the event, there are two ways to create FromEventPattern
and FromEvent
(in fact there are many, but I was involved in both), for a long time to find the relevant information ( this answer on SO helpful), and wrote some test code , finally understand about the Editor's Note.
The final code
Paste the code before the final method that can be used (in fact correct more than one way)
var watcher = new FileSystemWatcher();
watcher.Path = "d:\\test";
var observable = Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
ev => watcher.Changed += ev,
ev => watcher.Changed -= ev);
var d = observable.Throttle(TimeSpan.FromSeconds(5))
.Subscribe(
a => Console.WriteLine($"Watcher type:{a.EventArgs.ChangeType }, file:{a.EventArgs.Name }, sender: {a.Sender}"),
ex => Console.WriteLine("observer error:" + ex.ToString()),
() => Console.WriteLine("observer complete.")
Observable achieve understanding
Observable Observer for binding and the Event Source delegate, his role is that some of the filtering process may be performed (personal understanding).
Observer primarily through which to achieve OnNext
this a delegate, when there is Observable event is triggered, it will call the Observer registration OnNext
method, OnNext method is Action<T>
the type, and template parameters T
from Observable
specified when created.
.net events
.net in the event handler in line with EventHandler
the delegate format
public delegate void EventHandler(object sender, EventArgs e);
Two arguments, returns null.
Observable for distributed event handling observer, although events can be any custom events, but to conform to .net standard EventHandler
mode event, providing FromEventPattern
ways to create Observable, and other custom mode event, we FromEvent
create it.
The final two are functionally equivalent, can do with FromEvent FromEventPattern
function (requires more code), and vice versa (more trouble), I wrote a few examples to test this.
FromEvent
Both signatures (choose a generic)
//FromEvent
public static IObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>
(Func<Action<TEventArgs>, TDelegate> conversion,
Action<TDelegate> addHandler,
Action<TDelegate> removeHandler);
This is a common method of creating Observable.
-
TDelegate
: This is the type of event source -
TEventArgs
: This is actuallyOnNext
theT
parameters, rather thanTDelegate
the argument ,OnNext
it isAction<T>
, can only receive one parameter, the generic types to indicate the Observer createdOnNext
parameter handler need to be addressed -
conversion
: In general,TDelegate
andOnNext
the signature is different, this time need a converter function that willTdelegate
translate intoOnNext
calls -
addHandler/removeHandler
: Register and unregister event,Observer
call theSubscribe
registered subscription.In fact, can be seen,
Observable
the source of the event (in line typeTDelegate
) type, translate intoOnNext
calls.
To some extent, can be seen asevent
the+
operation (there may be a question that why rx this layer, observer capacity is actually on the filter handling of the incident, that in the event - on the path> event handler, an increase of various functions).
FromEventPattern
//FromEventPattern
public static IObservable<EventPattern<TEventArgs>> FromEventPattern<TDelegate, TEventArgs>(Action<TDelegate> addHandler, Action<TDelegate> removeHandler);
And the signature FromEvent
is substantially the same, except that at least one convension
conversion parameter.
This is because the function that is designed for interfacing .net standard EventHandler
types of events. EventHandler contains two parameters sender
and EventArgs
, and this will function i.e. sender and EventArgs two parameters configured to a EventPattern<EventArgs>
type of parameter passed to OnNext
.
In other words, the internal RX has helped us achieve .net standard for the type of event EventHandler conversion
conversion functions.
There are also noticed TDelegate
and TEventArgs
two parameters, which helped us to expand in line with EventHandler
the extended format type of event. The EventHandler EventArgs
can be designated as TEventArgs
the type of representative, EventHandler also be extended to the appropriate EventHandler<TEventArgs>
type of event format.
Sample Code
I based my original demand FileSystemWatcher
monitoring, wrote some sample code to verify the use and differences.
Observable Based on the FileSystemWatcher Changed
events, Observer of the OnNext
realization of all use the same printing functions, created by different methods of Observerbal, to achieve the same purpose.
Finally, the addition of a simultaneous monitoring Changed
and Renamed
event, and add code to my original anti-shake purposes.
Frame code is as follows:
//Create watcher
var watcher = new FileSystemWatcher();
watcher.Path = "d:\\test";
//creation of observable goes here
var observable = .....
//subscribe to observable
var d = observable
.Subscribe(
a => Console.WriteLine($"Watcher type:{a.ChangeType}, file:{a.Name}"),
ex => Console.WriteLine("observer error:" + ex.ToString()),
() => Console.WriteLine("observer complete.")
);
//Enable watcher
watcher.EnableRaisingEvents = true;
FromEventPattern
Since the Changed
event in line with the signature EventHandler<FileSystemEventArgs>
type, so in this way can be defined as follows observable
:
var observable = Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
ev => watcher.Changed += ev,
ev => watcher.Changed -= ev).Select(x => x.EventArgs);
Note that the final Select
, it will EventPattern<FileSystemEventArgs>
be converted to FileSystemEventArgs
.
FromEvent
If you pass FromEvent
, you will need to EventHandler<FileSystemEventArgs>
translate into OnNext
calls.
If you do not use FromEvent through conversion function, create the code runs the agent fails:
//THIS IS WRONG!
var observable = Observable.FromEvent<FileSystemEventHandler, FileSystemEventArgs>(
ev => watcher.Changed += ev,
ev => watcher.Changed -= ev);
By conversion
The need to increase a conversion function transformation
var observable = Observable.FromEvent<FileSystemEventHandler, FileSystemEventArgs>(
handler =>
{
return (object sender, FileSystemEventArgs fa) => handler(fa);
}
, ev => watcher.Changed += ev,
ev => watcher.Changed -= ev);
By modifying agent type source
A little trouble, but as a showcase of use FromEvent, when the signature is the same, no need for conversion overloaded.
First, define the proxy class using observable
private delegate void MyWatcherDelegate(FileSystemEventArgs args);
private static event MyWatcherDelegate MyWatcherEvent;
Then watcher event subscription to the custom of MyWatcherEvent
the event. (Note that since anonymous function is used here, it can not be removed from the Watcher event)
watcher.Changed += (sender, args) =>
{
Console.WriteLine("Intermediate watcher handler delegate");
if (null != MyWatcherEvent)
{
Console.WriteLine("Call through custom event");
MyWatcherEvent(args);
}
};
Finally created by FromEvent Observable, this time for MyWatcherDelegate
compliance with OnNext signature, so no conversion method can be successfully created.
var observable = Observable.FromEvent<MyWatcherDelegate, FileSystemEventArgs>(
ev => MyWatcherEvent += ev,
ev => MyWatcherEvent -= ev);
The combined Renamed and Changed events
In fact, the title here and little to do, but to expand the use of Observable.
By Merge
can simultaneously monitor different observable signatures of two events:
var o1 = Observable.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
ev => watcher.Changed += ev,
ev => watcher.Changed -= ev);
var o2 = Observable.FromEventPattern<RenamedEventHandler, RenamedEventArgs>(
ev => watcher.Renamed += ev,
ev => watcher.Renamed -= ev)
.Select(x => new System.Reactive.EventPattern<FileSystemEventArgs>(x.Sender, x.EventArgs));
var observable = Observable.Merge(o1, o2);