【问题标题】:Canceling await tasks without explicit checks在没有明确检查的情况下取消等待任务
【发布时间】:2014-02-20 15:40:00
【问题描述】:

我正在开发一个使用 C# 编写 NPC 脚本的在线游戏服务器。为了获得无状态的 NPC,我使用了枚举器,当我必须等待来自客户端的响应时让步,并在我得到它后调用 MoveNext。

Talk()
    Msg("test");
    Select("Yes", "No");
    yield return true;
    Msg(Response);

(简化示例,实际中的屈服要复杂一些。)

这很好用,但 async/wait 会让它更简洁、更容易、更灵活。

Talk()
    Msg("test");
    Msg(await Select("Yes", "No"));

玩弄 async/wait 我发现我唯一的问题是脚本不像发送一些消息那么简单。从主 Talk 函数调用其他函数时,我必须等待它们,因为否则执行不会停止。其他函数也可以调用更多,创建未知数量的等待。

Talk()
    Msg("test");
    await OtherTalk();
    Msg("end"); // would be called right away

OtherTalk()
    Msg("test2");
    Msg(await Select("Yes", "No"));

如果我在这种“潜谈”方法中关闭 NPC,我可能会留下相当多的任务悬而未决,因为我不会返回链条。 NPC 关闭,没有更多响应,任务继续等待。

解决这个问题的方法是让链条恢复原状,在等待此类函数后进行显式检查,以检查 NPC 是否在某处关闭。但我希望它们尽可能简单和直接,坦率地说,在每次调用函数之后都有一个 if 对我来说太乏味了。服务器软件也将被新手使用,他们可能会忘记这样的检查,这可能会导致问题,这取决于脚本的作用。

我现在的实际问题是,是否有人可以想办法取消任务,而无需明确检查脚本本身。

【问题讨论】:

  • 使用 TPL 的内置取消功能;见CancellationTokenSource
  • 这需要在脚本中进行检查,因为任务会返回并且“父”函数不应该继续执行。
  • 否;等待取消的任务也会取消调用者。您只需要定期拨打token.ThrowIfCancellationRequested() 电话。
  • 哦,误解了那个类的作用。这正是我所需要的!我现在在开始时创建一个令牌(脚本类的私有字段)并将其传递给我在 Select 方法中使用的 SemaphoreSlim,我用它来等待响应。如果我得到关闭的 NPC 数据包,我会取消令牌,这会抛出并让我回到 start 方法。在我自己的 Close 方法中,我自己抛出异常,以便快速退出。我认为这没有任何问题,并且它对脚本编写者隐藏了所有内容。如果您添加答案,我会接受:)

标签: c# .net asynchronous async-await


【解决方案1】:

TPL 具有内置的取消功能。

让您的所有函数都接受CanellationToken,并在调用每个异步函数时传递令牌。

在函数内部不时调用token.ThrowIfCancellationRequested(),整个异步调用链将中止,直到您处理取消。

【讨论】:

    【解决方案2】:

    您可以安装一个可以取消的自定义SynchronizationContext。在取消时,它只会停止调用延续。 async 方法将在下一个 await 之后立即停止。如果没有任何东西可以保留这些任务,它们将被 GC 处理并离开。

    请注意,即使finally 块也不会执行这种方式。 using 清理不会发生等。您的代码必须经过强化才能在这些情况下安全。

    【讨论】:

    • 虽然看起来我不会使用这个方法,但读到 SynchronizationContext 仍然很有趣,从来没有听说过(可能是因为我很少做 GUI 编程)。这是一个非常有趣的想法,+1。
    【解决方案3】:

    这是一个简短的答案。

    如果您想安全中止,任务取消必须始终是合作取消。

    【讨论】:

    • @Aron 哪一个适合你。我是一个机会均等的拼写者。
    猜你喜欢
    • 2015-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 1970-01-01
    • 1970-01-01
    • 2015-11-02
    • 2010-10-28
    相关资源
    最近更新 更多