在扩展方法中添加事件侦听器

时间:2020-03-24 16:32:01

标签: c# events async-await event-handling

在我的主班里,我有这样的活动

private event System.Action OnActionFinished;

并且知道await会调用GetAwaiter()方法,所以我有System.Action扩展方法: `

public static TaskAwaiter<object> GetAwaiter(this Action action)
{
    TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
    action += () => tcs.SetResult(null);
    return tcs.Task.GetAwaiter();
}

以便能够以await OnActionFinished;方法编写async

public async Task ExecuteTurns(Queue<TurnAction> turnActions)
{
    foreach (TurnAction turn in turnActions)
    {
        Action<Vector2> TurnMethod = null;
        switch (turn.TurnType)
        {
            case TurnType.Walk:
                TurnMethod = Walk;
                break;
            case TurnType.Jump:
                TurnMethod = Jump;
                break;
            case TurnType.Shoot:
                TurnMethod = rangedWeapon.Shoot;
                break;
        }
        Task.Run(async () => {
            TurnMethod(turn.Direction);
            });
        await OnActionFinished;
    }
}

OnActionFinished在Walk,Jump和Shoot方法的末尾被调用。

为什么这不起作用?

1 个答案:

答案 0 :(得分:1)

Action是不可变的类型。您不会更改该动作,以使其在调用时执行不同的行为,而是在创建一个新的动作(然后您什么也不做)来完成您的TCS。

一般来说,能够基于任意事件构造一个Task是相当困难的,并且要实现完全类型安全是不可能的。 You can see some of the difficulties with doing that here。现在,要基于特定对象上的特定事件创建一个Task,这很容易(同样,请参见前面链接的问题)。

这主要源于C#语言本身围绕事件公开的功能,完全不允许这样做。

相关问题