的Combinator的您正在寻找的是CombineLatest
假设你有一个这样的类:
public class Foo
{
public delegate void FooEventHandler(object sender, EventArgs args);
public event FooEventHandler FirstEvent = delegate {};
public event FooEventHandler SecondEvent = delegate {};
public event FooEventHandler ThirdEvent = delegate {};
public void DoIt()
{
FireOne();
FireTwo();
FireThree();
}
public void FireOne()
{
Console.WriteLine("Firing event 1...");
Thread.Sleep(1000);
FirstEvent(this, new EventArgs());
}
public void FireTwo()
{
Console.WriteLine("Firing event 2...");
Thread.Sleep(1000);
SecondEvent(this, new EventArgs());
}
public void FireThree()
{
Console.WriteLine("Firing event 3...");
Thread.Sleep(1000);
ThirdEvent(this, new EventArgs());
}
}
首先你要“转换”这些事件来Observable
:
var foo = new Foo();
var firstWatcher = Observable.FromEventPattern(foo, "FirstEvent");
var secondWatcher = Observable.FromEventPattern(foo, "SecondEvent");
var thirdWatcher = Observable.FromEventPattern(foo, "ThirdEvent");
现在你会想要“所有这些都已经发射的时候只有发射”选择器,它是CombineLatest
:
var allDone = Observable.CombineLatest(firstWatcher, secondWatcher, thirdWatcher);
并对其进行测试:
using(allDone.Subscribe(_ => Console.WriteLine("Boop! You sunk my battleship!")))
{
foo.DoIt();
}
另类 “测试工具”:
var foo = new Foo();
var firstWatcher = Observable.FromEventPattern(foo, "FirstEvent");
var secondWatcher = Observable.FromEventPattern(foo, "SecondEvent");
var thirdWatcher = Observable.FromEventPattern(foo, "ThirdEvent");
var allDone = Observable.CombineLatest(firstWatcher, secondWatcher, thirdWatcher);
// keep a handle on the subscription
IDisposable subscription = null;
// to prevent premature exiting...
var blocker = new ManualResetEvent(false);
// explicit subscribe
subscription = allDone.Subscribe(
whoCares =>
{
Console.WriteLine("BOOM! We're done!");
// always clean up after yourself
if(subscription != null)
{
subscription.Dispose();
}
// it's ok, we can quit now
blocker.Set();
});
foo.DoIt();
// Wait until it's clear to go ahead...
blocker.WaitOne();
感谢您的帮助JerKimball。很有用。如果事件是异步的,例如如果我们调用FireOne | Two | Three并且在进行一些异步调用而不触发事件后立即返回这些事件?我试着用我的事件,它看起来像使用(allDone ...)将在事件结束前退出,因此allDone处理程序不会被调用(除非我做错了什么)。 – Flack
例如,如果public void FireOne()包含int msDelay = 8000,那么您是否有如何使您当前的示例工作的示例? 任务任务= Task.Factory.StartNew(()=> Thread.sleep代码(msDelay)) .ContinueWith((任务起动)=> { Console.WriteLine( “EVENT 1”); FirstEvent(这一点,新EventArgs()); },TaskContinuationOptions.LongRunning);' – Flack
实际发生的情况是,在我蹩脚的小例子-harness中,程序在事件触发前“结束” - 更重要的是,创建的订阅'allDone.Subscribe'正在处理中。在这个'using'的大括号之前放置一个'Console.ReadLine','Thread.Sleep(10000)'或任何你想要的东西(或者存储它自己创建和处理的'IDisposable') – JerKimball