Эта цитата из ответа Тима Робинсона заставила меня задуматься:
То, что вы делаете, это превращение последовательности push (появления события) в последовательность pull (вызов IEnumerable).
Превратить последовательность push в последовательность pull сложно, и корень моих проблем здесь. Но обратное (превращение последовательности вытягивания в последовательность выталкивания) тривиально, и это понимание дало мне решение. Я изменил LongRunningMethod
на внутреннюю перечисляемую версию, с тривиальным рефакторингом замены каждого обратного вызова события на yield return
и добавления yield break
в конце. Затем я превратил существующий LongRunningMethod
в оболочку, которая просто запускает событие для всего возвращаемого:
internal IEnumerable<InterestingObject> FindInterestingObjects()
{
/* etc */
}
public void LongRunningMethod()
{
foreach (var obj in FindInterestingObjects())
{
OnInterestingEvent(obj);
}
}
Это сохраняет общедоступный интерфейс, давая при этом аккуратное перечисление, которое я могу использовать для сценариев, которые требуют его. Как существенная дополнительная выгода, это также позволяет мне заблаговременно отказаться от длинных вычислений, если я этого захочу, что будет трудно сделать с версиями на основе событий или многопоточными.