Coroutine.cs 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. namespace Caliburn.Micro.Core {
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Threading.Tasks;
  5. /// <summary>
  6. /// Manages coroutine execution.
  7. /// </summary>
  8. public static class Coroutine {
  9. static readonly ILog Log = LogManager.GetLog(typeof(Coroutine));
  10. /// <summary>
  11. /// Creates the parent enumerator.
  12. /// </summary>
  13. public static Func<IEnumerator<IResult>, IResult> CreateParentEnumerator = inner => new SequentialResult(inner);
  14. /// <summary>
  15. /// Executes a coroutine.
  16. /// </summary>
  17. /// <param name="coroutine">The coroutine to execute.</param>
  18. /// <param name="context">The context to execute the coroutine within.</param>
  19. /// /// <param name="callback">The completion callback for the coroutine.</param>
  20. public static void BeginExecute(IEnumerator<IResult> coroutine, CoroutineExecutionContext context = null, EventHandler<ResultCompletionEventArgs> callback = null) {
  21. Log.Info("Executing coroutine.");
  22. var enumerator = CreateParentEnumerator(coroutine);
  23. IoC.BuildUp(enumerator);
  24. if (callback != null) {
  25. ExecuteOnCompleted(enumerator, callback);
  26. }
  27. ExecuteOnCompleted(enumerator, Completed);
  28. enumerator.Execute(context ?? new CoroutineExecutionContext());
  29. }
  30. /// <summary>
  31. /// Executes a coroutine asynchronous.
  32. /// </summary>
  33. /// <param name="coroutine">The coroutine to execute.</param>
  34. /// <param name="context">The context to execute the coroutine within.</param>
  35. /// <returns>A task that represents the asynchronous coroutine.</returns>
  36. public static Task ExecuteAsync(IEnumerator<IResult> coroutine, CoroutineExecutionContext context = null) {
  37. var taskSource = new TaskCompletionSource<object>();
  38. BeginExecute(coroutine, context, (s, e) => {
  39. if (e.Error != null)
  40. taskSource.SetException(e.Error);
  41. else if (e.WasCancelled)
  42. taskSource.SetCanceled();
  43. else
  44. taskSource.SetResult(null);
  45. });
  46. return taskSource.Task;
  47. }
  48. static void ExecuteOnCompleted(IResult result, EventHandler<ResultCompletionEventArgs> handler) {
  49. EventHandler<ResultCompletionEventArgs> onCompledted = null;
  50. onCompledted = (s, e) => {
  51. result.Completed -= onCompledted;
  52. handler(s, e);
  53. };
  54. result.Completed += onCompledted;
  55. }
  56. /// <summary>
  57. /// Called upon completion of a coroutine.
  58. /// </summary>
  59. public static event EventHandler<ResultCompletionEventArgs> Completed = (s, e) => {
  60. if(e.Error != null) {
  61. Log.Error(e.Error);
  62. }
  63. else if(e.WasCancelled) {
  64. Log.Info("Coroutine execution cancelled.");
  65. }
  66. else {
  67. Log.Info("Coroutine execution completed.");
  68. }
  69. };
  70. }
  71. }