使用事件处理程序的yield

JSB*_*ոգչ 2 c# events yield

我有一个方法Foo.LongRunningMethod(),它做了一些非常复杂的处理,可能会持续很长时间.一路上,它会Foo.InterestingEvent在遇到某种情况时触发.我希望能够公开这些事件的枚举,并且我希望能够在LongRunningMethod实际完成之前开始迭代.换句话说,我想要的是这样的:

public IEnumerable<InterestingObject> GetInterestingObjects()
{
    foo.InterestingEvent += (obj) => { yield return obj; }
    foo.LongRunningMethod();

    yield break;
}
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用,因为你不能yield return从匿名方法(并且因为使用的方法yield无法返回void,我们的事件处理程序所做的那样)的合理原因.还有另一个成语允许我完成这个吗?或者这只是一个坏主意?

Tim*_*son 5

您希望能够订阅来自的事件流,LongRunningMethod并且当事件发生时,从而产生另一个值IEnumerable?您可能会发现.NET Reactive Extensions很有用:http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx

反应性扩展为您提供IObservable,实际上是推送式IEnumerable.您可以IObservable围绕事件(例如您的InterestingEvent)创建包装器,并从那里对其执行可枚举式处理(例如生成对象流).

编辑: "除了采用微软的新图书馆之外,还有一个让我能够做到这一点的成语吗?你正在做的是将推送序列(事件的发生)转换为拉动序列(调用IEnumerable).

拉动和推动可能不会协调,因此您需要在某处缓冲在拉动之前推动的新值.最直接的方式可能是采用生产者 - 消费者安排:将这些安排推送到List<T>调用者所使用的内容中GetInterestingObjects.

根据事件的引发方式,您可能需要将生产者和使用者放在不同的线程上.(当你要求它在一个IObservable和一个之间进行转换时,所有这些都是反应式扩展最终会做的事情IEnumerable.)