取消等待任务而无需显式检查 [英] Canceling await tasks without explicit checks

查看:84
本文介绍了取消等待任务而无需显式检查的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发使用C#的NPC脚本的在线游戏服务器.为了获得无状态的NPC,我使用了枚举器,在必须等待客户端响应时屈服,并在获得响应后调用MoveNext.

I'm developing an online game server that uses C# for its NPC scripts. To get stateless NPCs I'm using enumerators, yielding when I have to wait for a response from the client, and calling MoveNext once I got it.

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

(简化的例子,实际的收益率要复杂一些.)

(Simplified example, the yielding is a little more complex in reality.)

这工作正常,但是异步/等待会使它更整洁,更轻松,更灵活.

This is working fine, but async/wait would make make it cleaner, easier, and more flexible.

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

玩异步/等待,我发现我唯一的问题是脚本不像发送一些消息那样简单.从主要Talk函数调用其他函数时,我必须等待它们,否则执行将不会停止.其他功能还可以调用更多功能,从而产生未知数量的等待.

Playing around with async/wait I've found my only problem to be that the scripts aren't as simple as sending some messages. When calling other functions from the main Talk function I have to await them, since the execution wouldn't stop otherwise. The other functions could also call even more, creating an unknown amount of awaits.

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

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

如果我用这样的副谈话"方法关闭NPC,我可能会悬空很多任务,因为我不会回到链上. NPC已关闭,没有更多响应,任务一直在等待.

If I close the NPC inside such a "sub talk" method I'd potentially leave quite a few tasks hanging in the air, because I wouldn't return up the chain. NPC closed, no more responses, tasks keep waiting.

解决此问题的方法是重新建立链,并在等待该函数后进行显式检查,以检查NPC是否已关闭.但是我希望它们尽可能简单明了,坦率地说,在每次调用函数后都添加if是否太单调乏味.该服务器软件还将由新手使用,他们可能会忘记这种检查,这可能会导致问题,具体取决于脚本的作用.

The solution to this problem would be going the chain back up, with explicit checks after the await of such a function, to check if the NPC was closed somewhere down the line. But I want them to be as simple and straight forward as possible, and frankly, having an if after each call of a function would be too tedious for my taste. The server software will also be used by newbies, who might forget such a check, which could lead to problems, depending on what the script does.

我现在的实际问题是,是否有人可以想到一种取消任务的方法,而无需对脚本本身进行显式检查.

My actual question now is if someone can think of a way to cancel the Tasks, without explicit checks in the scripts themselves.

推荐答案

TPL具有内置的取消功能.

The TPL has built-in cancellation features.

使所有函数都接受CanellationToken,并在调用每个异步函数时传递令牌.

Make all of your functions accept a CanellationToken, and pass the token along when calling every async function.

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

Every now and then, inside the functions, call token.ThrowIfCancellationRequested(), and the entire async callchain will abort, until you handle the cancellation.

这篇关于取消等待任务而无需显式检查的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆