Sic04/FrameworkLocal/UIClient/Caliburn.Micro/Core/Coroutine.cs

83 lines
3.1 KiB
C#

namespace Caliburn.Micro.Core {
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
/// <summary>
/// Manages coroutine execution.
/// </summary>
public static class Coroutine {
static readonly ILog Log = LogManager.GetLog(typeof(Coroutine));
/// <summary>
/// Creates the parent enumerator.
/// </summary>
public static Func<IEnumerator<IResult>, IResult> CreateParentEnumerator = inner => new SequentialResult(inner);
/// <summary>
/// Executes a coroutine.
/// </summary>
/// <param name="coroutine">The coroutine to execute.</param>
/// <param name="context">The context to execute the coroutine within.</param>
/// /// <param name="callback">The completion callback for the coroutine.</param>
public static void BeginExecute(IEnumerator<IResult> coroutine, CoroutineExecutionContext context = null, EventHandler<ResultCompletionEventArgs> 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());
}
/// <summary>
/// Executes a coroutine asynchronous.
/// </summary>
/// <param name="coroutine">The coroutine to execute.</param>
/// <param name="context">The context to execute the coroutine within.</param>
/// <returns>A task that represents the asynchronous coroutine.</returns>
public static Task ExecuteAsync(IEnumerator<IResult> coroutine, CoroutineExecutionContext context = null) {
var taskSource = new TaskCompletionSource<object>();
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<ResultCompletionEventArgs> handler) {
EventHandler<ResultCompletionEventArgs> onCompledted = null;
onCompledted = (s, e) => {
result.Completed -= onCompledted;
handler(s, e);
};
result.Completed += onCompledted;
}
/// <summary>
/// Called upon completion of a coroutine.
/// </summary>
public static event EventHandler<ResultCompletionEventArgs> 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.");
}
};
}
}