为TaskAwaiter添加异常捕获和OnError事件 (#49)

This commit is contained in:
milimoe 2023-08-26 13:22:01 +08:00 committed by GitHub
parent 820111e048
commit a814997a4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 14 deletions

View File

@ -3,7 +3,9 @@
public interface ITaskAwaiter public interface ITaskAwaiter
{ {
public bool IsCompleted { get; } public bool IsCompleted { get; }
public Exception Exception { get; }
public ITaskAwaiter OnCompleted(Action action); public ITaskAwaiter OnCompleted(Action action);
public ITaskAwaiter OnError(Action action);
} }
} }

View File

@ -12,9 +12,14 @@ namespace Milimoe.FunGame.Core.Library.Common.Architecture
/// </summary> /// </summary>
public readonly bool IsCompleted => awaiter.IsCompleted; public readonly bool IsCompleted => awaiter.IsCompleted;
/// <summary>
/// 捕获到的异常
/// </summary>
public readonly System.Exception Exception => awaiter.Exception;
/// <summary> /// <summary>
/// <para>内部实现类</para> /// <para>内部实现类</para>
/// <see cref="Service.TaskManager.TaskAwaiter"/> /// 实现参见 <see cref="Service.TaskManager.TaskAwaiter"/>
/// </summary> /// </summary>
private ITaskAwaiter awaiter; private ITaskAwaiter awaiter;
@ -28,9 +33,9 @@ namespace Milimoe.FunGame.Core.Library.Common.Architecture
} }
/// <summary> /// <summary>
/// <para>返回TaskAwaiter可以连续的调用方法</para> /// 返回TaskAwaiter可以连续的调用方法<para/>
/// <para>但是意义不大前一个OnCompleted方法并不会等待下一个方法</para> /// 但是意义不大前一个OnCompleted方法并不会等待下一个方法<para/>
/// <para>可以理解为并行广播</para> /// 可以理解为并行广播<para/>
/// </summary> /// </summary>
/// <param name="action"></param> /// <param name="action"></param>
/// <returns></returns> /// <returns></returns>
@ -39,5 +44,16 @@ namespace Milimoe.FunGame.Core.Library.Common.Architecture
awaiter = awaiter.OnCompleted(action); awaiter = awaiter.OnCompleted(action);
return this; return this;
} }
/// <summary>
/// 在捕获到异常时将触发Error事件
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
public TaskAwaiter OnError(Action action)
{
awaiter = awaiter.OnError(action);
return this;
}
} }
} }

View File

@ -24,19 +24,24 @@ namespace Milimoe.FunGame.Core.Service
private class TaskAwaiter : ITaskAwaiter private class TaskAwaiter : ITaskAwaiter
{ {
public bool IsCompleted => _IsCompleted; public bool IsCompleted => _IsCompleted;
public Exception Exception => _Exception;
private delegate void CompletedEvent(); private delegate void CompletedEvent();
private delegate void ErrorEvent();
private event CompletedEvent? Completed; private event CompletedEvent? Completed;
private event ErrorEvent? Error;
private bool _IsCompleted = false; private bool _IsCompleted = false;
private Exception _Exception = new();
internal TaskAwaiter(Action action) => _ = Worker(action); internal TaskAwaiter(Action action) => _ = Worker(action);
internal TaskAwaiter(Func<Task> function) => _ = Worker(function); internal TaskAwaiter(Func<Task> function) => _ = Worker(function);
/// <summary> /// <summary>
/// <para>返回ITaskAwaiter可以进一步调用方法</para> /// 返回ITaskAwaiter可以进一步调用方法<para/>
/// <para>但是意义不大前一个OnCompleted方法并不会等待下一个方法</para> /// 但是意义不大前一个OnCompleted方法并不会等待下一个方法<para/>
/// <para>可以理解为并行广播</para> /// 可以理解为并行广播<para/>
/// </summary> /// </summary>
/// <param name="action"></param> /// <param name="action"></param>
/// <returns></returns> /// <returns></returns>
@ -47,19 +52,46 @@ namespace Milimoe.FunGame.Core.Service
return this; return this;
} }
/// <summary>
/// 在捕获到异常时将触发Error事件
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
public ITaskAwaiter OnError(Action action)
{
Error += new ErrorEvent(action);
return this;
}
private async Task Worker(Action action) private async Task Worker(Action action)
{
try
{ {
await Task.Run(action); await Task.Run(action);
_IsCompleted = true; _IsCompleted = true;
Completed?.Invoke(); Completed?.Invoke();
} }
catch (Exception e)
{
_Exception = e;
Error?.Invoke();
}
}
private async Task Worker(Func<Task> function) private async Task Worker(Func<Task> function)
{
try
{ {
await function(); await function();
_IsCompleted = true; _IsCompleted = true;
Completed?.Invoke(); Completed?.Invoke();
} }
catch (Exception e)
{
_Exception = e;
Error?.Invoke();
}
}
} }
} }
} }