How to yield return inside anonymous methods?

Joan Venge picture Joan Venge · Mar 23, 2011 · Viewed 15.6k times · Source

Basically I have an anonymous method that I use for my BackgroundWorker:

worker.DoWork += ( sender, e ) =>
{
    foreach ( var effect in GlobalGraph.Effects )
    {
        // Returns EffectResult
        yield return image.Apply (effect);
    }
};

When I do this the compiler tells me:

"The yield statement cannot be used inside an anonymous method or lambda expression"

So in this case, what's the most elegant way to do this? Btw this DoWork method is inside a static method, in case that matters for the solution.

Answer

Lasse V. Karlsen picture Lasse V. Karlsen · Mar 23, 2011

Unfortunately you can't.

The compiler does not allow you to combine the two "magic" pieces of code. Both involve rewriting your code to support what you want to do:

  1. An anonymous method is done by moving the code to a proper method, and lifting local variables to fields on the class with that method
  2. An iterator method is rewritten as a state machine

You can, however, rewrite the code to return the collection, so in your particular case I would do this:

worker.DoWork += ( sender, e ) =>
{
    return GlobalGraph.Effects
        .Select(effect => image.Apply(effect));
};

though it looks odd for an event (sender, e) to return anything at all. Are you sure you're showing a real scenario for us?


Edit Ok, I think I see what you're trying to do here.

You have a static method call, and then you want to execute code in the background, and then return data from that static method once the background call completes.

This is, while possible, not a good solution since you're effectively pausing one thread to wait for another, that was started directly before you paused the thread. In other words, all you're doing is adding overhead of context switching.

Instead you need to just kick off the background work, and then when that work is completed, process the resulting data.