[英]Using Rx to synchronize asynchronous events
我想充分利用Reactive Extensions for .NET(Rx) ,并希望得到一些关于做一些基本任务的意见。 为了说明我正在尝试做什么,我有一个人为的例子,我有一个带有异步事件的外部组件:
class Component {
public void BeginStart() { ... }
public event EventHandler Started;
}
通过调用BeginStart()
启动该组件。 此方法立即返回,稍后,当组件完成启动时,将触发Started
事件。
我想通过包装组件来创建一个同步启动方法,并等待Started
事件被触发。 这是我到目前为止所提出的:
class ComponentWrapper {
readonly Component component = new Component();
void StartComponent() {
var componentStarted =
Observable.FromEvent<EventArgs>(this.component, "Started");
using (var startedEvent = new ManualResetEvent(false))
using (componentStarted.Take(1).Subscribe(e => { startedEvent.Set(); })) {
this.componenet.BeginStart();
startedEvent.WaitOne();
}
}
}
我想摆脱ManualResetEvent
,我希望Rx有一个解决方案。 但是怎么样?
PL的答案如果完全符合你的规范,但我认为你可以通过不与RX对战来获得更好的结果.First()但是通过为你的组件创建一个observable来接受它:
public static IObservable<Unit> AsObservable(this Component component)
{
return Observable.Defer(() =>
{
component.BeginStart();
return Observable
.FromEvent<EventArgs>(component, "Started")
.Select(_ => new Unit());
});
}
然后你可以用它作为阻塞:
new Component().AsObservable().First();
非阻塞:
new Component().AsObservable().Subscribe(_ => Console.WriteLine("Done"));
热:
var pub = new Component().AsObservable().Publish();
pub.Subscribe(_ => Console.WriteLine("Sub1"));
pub.Subscribe(_ => Console.WriteLine("Sub2"));
pub.Connect(); // started just once per two subscriptions
可组合:
new Component().AsObservable().Delay(TimeSpan.FromSeconds(1));
等等...
编辑:对于您必须等待并收集信息的多个事件的情况,可以使用以下变体:
public static IObservable<EventArgs> AsObservable(this Component component)
{
return Observable.Defer(() =>
{
component.BeginStart();
return
Observable.FromEvent<EventArgs>(component, "Started1").Take(1)
.Merge(
Observable.FromEvent<EventArgs>(component, "Started2").Take(1))
.Select(evt => evt.EventArgs);
});
}
有了这个,如果你想阻止直到完成,你可以使用.AsObservable.Last()
。
这样的事情应该这样做:
var replay = Observable
.FromEvent<EventArgs>(this.component, "Started")
.Replay();
replay.Connect();
component.BeginStart();
replay.First();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.