Trừ khi tôi bỏ lỡ điều gì đó, bạn không thể làm những gì bạn đang yêu cầu.
(Tôi không có một câu trả lời cho bạn, vì vậy hãy đọc qua lời giải thích của tôi về lý do tại sao bạn không thể làm những gì bạn đang làm đầu tiên, và sau đó đọc trên.)
Bạn đầy đủ phương pháp sẽ giống như thế này:
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);
}
};
}
Nếu chúng ta giả định rằng mã của bạn là "hợp pháp" sau đó khi GetSomeValues
được gọi là, mặc dù các handler DoWork
được thêm vào worker
, khái niệm lambda không được thực hiện cho đến khi sự kiện DoWork
là bắn. Vì vậy, các cuộc gọi đến GetSomeValues
hoàn thành mà không trả lại bất kỳ kết quả và lamdba có thể hoặc có thể không nhận được gọi là ở giai đoạn sau - đó là sau đó quá muộn cho người gọi của phương pháp GetSomeValues
anyway.
Câu trả lời hay nhất của bạn là sử dụng Rx.
Rx quay IEnumerable<T>
trên đầu. Thay vì yêu cầu các giá trị từ một số đếm, Rx có các giá trị được đẩy tới bạn từ một số IObservable<T>
.
Vì bạn đang sử dụng nhân viên hỗ trợ nền và trả lời sự kiện bạn đang có hiệu quả với các giá trị được đẩy vào bạn. Với Rx nó trở nên dễ dàng để làm những gì bạn đang cố gắng làm.
Bạn có một vài tùy chọn. Có lẽ là đơn giản nhất là để làm điều này:
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)
);
}
Bây giờ người gọi của phương pháp GetSomeValues
của bạn sẽ làm điều này:
GetSomeValues().Subscribe(ers =>
{
foreach (var er in ers)
{
// process each er
}
});
Nếu bạn biết rằng DoWork
chỉ sẽ bắn một lần, sau đó phương pháp này có thể là một tốt hơn một chút:
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();
}
Mã này có vẻ phức tạp hơn một chút, nhưng nó chỉ biến một sự kiện làm việc thành luồng EffectResult
các đối tượng.
Sau đó, mã gọi trông như thế này:
GetSomeValues().Subscribe(er =>
{
// process each er
});
Rx thậm chí có thể được sử dụng để thay thế người lao động nền. Đây có thể là lựa chọn tốt nhất cho bạn:
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();
}
Mã gọi giống như ví dụ trước. Scheduler.ThreadPool
cho Rx biết cách "lên lịch" việc xử lý đăng ký cho người quan sát.
Tôi hy vọng điều này sẽ hữu ích.
Nhân viên nền tạo 'ảnh' hoặc điền vào 'GlobalGraph.Effects' có đếm được không? – Enigmativity
Có BW đang tạo ra hình ảnh nhưng EffectResult có trạng thái về hiệu ứng, không phải dữ liệu hình ảnh hay bất cứ thứ gì như thế. –
bản sao có thể có của [Trong C#, tại sao một phương thức nặc danh không thể chứa một tuyên bố về lợi nhuận?] (Http://stackoverflow.com/questions/1217729/in-c-why-cant-an-anonymous-method-contain- a-yield-statement) –