的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