namespace Caliburn.Micro.Core { using System; using System.Collections.Generic; using System.Threading.Tasks; /// /// Manages coroutine execution. /// public static class Coroutine { static readonly ILog Log = LogManager.GetLog(typeof(Coroutine)); /// /// Creates the parent enumerator. /// public static Func, IResult> CreateParentEnumerator = inner => new SequentialResult(inner); /// /// Executes a coroutine. /// /// The coroutine to execute. /// The context to execute the coroutine within. /// /// The completion callback for the coroutine. public static void BeginExecute(IEnumerator coroutine, CoroutineExecutionContext context = null, EventHandler callback = null) { Log.Info("Executing coroutine."); var enumerator = CreateParentEnumerator(coroutine); IoC.BuildUp(enumerator); if (callback != null) { ExecuteOnCompleted(enumerator, callback); } ExecuteOnCompleted(enumerator, Completed); enumerator.Execute(context ?? new CoroutineExecutionContext()); } /// /// Executes a coroutine asynchronous. /// /// The coroutine to execute. /// The context to execute the coroutine within. /// A task that represents the asynchronous coroutine. public static Task ExecuteAsync(IEnumerator coroutine, CoroutineExecutionContext context = null) { var taskSource = new TaskCompletionSource(); BeginExecute(coroutine, context, (s, e) => { if (e.Error != null) taskSource.SetException(e.Error); else if (e.WasCancelled) taskSource.SetCanceled(); else taskSource.SetResult(null); }); return taskSource.Task; } static void ExecuteOnCompleted(IResult result, EventHandler handler) { EventHandler onCompledted = null; onCompledted = (s, e) => { result.Completed -= onCompledted; handler(s, e); }; result.Completed += onCompledted; } /// /// Called upon completion of a coroutine. /// public static event EventHandler Completed = (s, e) => { if(e.Error != null) { Log.Error(e.Error); } else if(e.WasCancelled) { Log.Info("Coroutine execution cancelled."); } else { Log.Info("Coroutine execution completed."); } }; } }