Если я чего-то не упускаю, ты не можешь делать то, о чем просишь.
(У меня есть для вас ответ, поэтому сначала прочтите мое объяснение того, почему вы не можете делать то, что делаете, а затем читайте дальше.)
Полный метод будет выглядеть примерно так:
public static IEnumerable<EffectResult> GetSomeValues()
{
// code to set up worker etc
worker.DoWork += ( sender, e ) =>
{
foreach ( var effect in GlobalGraph.Effects )
{
// Returns EffectResult
yield return image.Apply (effect);
}
};
}
Если мы предположим, что ваш код был "допустимым", то при вызове GetSomeValues
, даже если обработчик DoWork
добавлен в worker
, лямбда-выражение не выполняется до тех пор, пока не будет запущено событие DoWork
. Таким образом, вызов GetSomeValues
завершается без возврата каких-либо результатов, и lamdba может или не может быть вызван на более позднем этапе, что в любом случае будет слишком поздно для вызывающего метода GetSomeValues
.
Ваш лучший ответ - использовать Rx.
Rx переворачивает IEnumerable<T>
с ног на голову. Вместо того, чтобы запрашивать значения из перечислимого, Rx имеет значения, переданные вам из IObservable<T>
.
Поскольку вы используете фонового работника и отвечаете на событие, вы уже фактически получаете значения, отправленные вам. С Rx становится легко делать то, что вы пытаетесь сделать.
У вас есть несколько вариантов. Наверное, самое простое - это сделать так:
public static IObservable<IEnumerable<EffectResult>> GetSomeValues()
{
// code to set up worker etc
return from e in Observable.FromEvent<DoWorkEventArgs>(worker, "DoWork")
select (
from effect in GlobalGraph.Effects
select image.Apply(effect)
);
}
Теперь вызывающие ваш GetSomeValues
метод будут делать это:
GetSomeValues().Subscribe(ers =>
{
foreach (var er in ers)
{
// process each er
}
});
Если вы знаете, что DoWork
сработает только один раз, тогда этот подход может быть немного лучше:
public static IObservable<EffectResult> GetSomeValues()
{
// code to set up worker etc
return Observable
.FromEvent<DoWorkEventArgs>(worker, "DoWork")
.Take(1)
.Select(effect => from effect in GlobalGraph.Effects.ToObservable()
select image.Apply(effect))
.Switch();
}
Этот код выглядит немного сложнее, но он просто превращает отдельное событие do work в поток EffectResult
объектов.
Тогда вызывающий код выглядит так:
GetSomeValues().Subscribe(er =>
{
// process each er
});
Rx можно даже использовать для замены фонового рабочего. Возможно, это лучший вариант для вас:
public static IObservable<EffectResult> GetSomeValues()
{
// set up code etc
return Observable
.Start(() => from effect in GlobalGraph.Effects.ToObservable()
select image.Apply(effect), Scheduler.ThreadPool)
.Switch();
}
Вызывающий код такой же, как в предыдущем примере. Scheduler.ThreadPool
сообщает Rx, как «запланировать» обработку подписок для наблюдателя.
Надеюсь, это поможет.
person
Enigmativity
schedule
23.03.2011
image
или заполняетGlobalGraph.Effects
перечислимый? - person Enigmativity   schedule 24.03.2011