Passing parameters between coroutines call

Topics: Actions & Coroutines
Jun 9, 2011 at 10:19 PM
Edited Jun 9, 2011 at 10:20 PM

Hey Guys,

I was using Caliburn's way of handling coroutines to study coroutines with a friend. 


We had the following question :
"How can I pass any value from one coroutine to the other ?"

So we just quickly added a single button to the ShellView and called it "Coroutine" so that it would call the Coroutine method below

We just made a really simple new EventHandler that has a new property. We set that on the first new coroutine and use it on the second.


In Code :
 

    [Export(typeof(IShell))]
    public class ShellViewModel : IShell 
    {
        public IEnumerable<IResult> Coroutine()
        {
            yield return new Coroutine1();
            yield return new Coroutine2();
        }
    }

    public class Coroutine1 : IResult
    {
        public void Execute(ActionExecutionContext context)
        {
            WebRequest req = WebRequest.Create("http://www.google.com");
            req.BeginGetResponse((a) =>
            {
                Debug.WriteLine("Hello Console 1");
                Completed(this, new NewResultCompletionEventArgs() { Sample = "Sample" });    
            } , null);
        }
        public event System.EventHandler<ResultCompletionEventArgs> Completed = delegate { };
    }

    public class Coroutine2 : IResult
    {
        public void Execute(ActionExecutionContext context)
        {
            Debug.WriteLine("Hello Console " + ((NewResultCompletionEventArgs)context.EventArgs).Sample);
            Completed(this, new ResultCompletionEventArgs());
        }

        public event System.EventHandler<ResultCompletionEventArgs> Completed = delegate { };
    }

    public class NewResultCompletionEventArgs : ResultCompletionEventArgs
    {
        public String Sample { get; set; }
    }

 

 

To make Caliburn support this, all we did was add one line in the source code (Class SequentialResult) :

Line 59:
context.EventArgs = args;

A snippet of the code :

            if(moveNextSucceeded) {
                try {
                    var next = enumerator.Current;
                    IoC.BuildUp(next);
                    next.Completed += ChildCompleted;
                    context.EventArgs = args;
                    next.Execute(context);
                }
                catch(Exception ex) {
                    OnComplete(ex, false);
                    return;
                }
            }

 

 

What do you think ? We're not sure this is the best way to do it...we are just starting to learn about coroutines :) 

Thanks, 

Alvaro Oliveira.

 

Coordinator
Jun 10, 2011 at 2:15 AM

The the context's event args is where the event args from the trigger are stored. So, if you had an action of coroutine that needed those args, you would be overwriting it. If you wanted to do this without altering the original source, there's a propery bag on the ActionExeucitionContext you can stuff anything into. You just need to be careful about using it in this way so that you don't get a memory leak. Normally, I use coroutines like this:

 

var query = new QueryBackend();

yield return query;

 

if(query.Result.IsSuccess){

    var anotherQuery = new AnotherBackendQuery(query.Result);

    yield anotherQuery;

 

    //do something with anotherQuery.Result

}

Jun 10, 2011 at 9:58 PM

Hey Rob, 

Thanks for responding!

Thanks for pointing out how to achieve what we wanted without any source changes. We are using the source to learn and it's been great! CaliburnMicro is a true gem that made us like doing Silverlight development.

Thanks again,

Alvaro Oliveira.