System.Reactive基础——转换.Net事件
System.Reactive把时间当做陆陆续续传来的数据序列。可以把System.Reactive视作LINQ to Events(基于IObservable<T>)。区别是,System.Reactive是推式模型,这意味着查询定义了程序如何响应事件的到来。
若要使用System.Reactive,需要在应用程序中安装用于System.Reactiv的NuGet包
问题
假设需要把某个事件视作System.Reactive输入流,并在每次执行时间时,通过OnNext生成数据。
解决方案
Observable类定义了一些事件转换器。大多数的.NET框架事件与FromEventPattern兼容,但如果存在不遵循常见形式的事件,则可以转而使用FromEvent
如果事件委托类型是EventHandler<T>,那么FromEventPattern是最适用的。
var progress=new Progress<int>();
IObservable<EventPattern<int> progressReports=Observable.FromEventPattern<int>(
handler=> progress.ProgressChanged+=handler,
handler=>progress.ProgressChanged-=handler);
progressReports.Subscribe(data=>Trace.WriteLine("OnNext:"+data.EventArgs));
可以把较老的事件用FromEventPattern包装起来:
var timer=new System.Timers.Timer(interval:1000){Enable=true};
IObservable<EventPattern<ElapsedEventArgs>> ticks=Observable.FromEventPattern<ElapsedEventHandler,ElapsedEventArgs>(
handler=>(s,a)=>handler(s,a),
handler=>timer.Elapsed+=handler,
handler=>timer.Elapsed-=handler
);
tick.Subscribe(data=>Trace.WriteLine("OnNext:"+data.EventArgs.SignalTime));
讨论
对System.Reactive可观察对象而言,事件是一种常见的数据源。在标准事件格式中,第1个参数表示发送者,第二个参数表示事件参数类型,如果遇到不寻常的事件类型,那么仍旧可以使用Observable.FromEvent方法重载,把他们包装秤可观察对象。
当事件被包装成可观察对象时,每次执行事件都会调用OnNext.在处理AsyncCompletedEventArgs时,这会导致出乎意料的行为,因为所有异常都是随着数据(OnNext)而不是错误(onError)来传递的。