Я разрабатываю сервер онлайн-игр, который использует C# для своих сценариев NPC. Чтобы получить NPC без гражданства, я использую счетчики, уступая, когда мне нужно ждать ответа от клиента и вызывать MoveNext, как только я его получу.Отмена ожидающих задач без явных проверок
Talk()
Msg("test");
Select("Yes", "No");
yield return true;
Msg(Response);
(упрощенный пример, податливость является немного более сложным, на самом деле.)
Это работает отлично, но асинхронная/ожидание бы сделать его чище, проще и более гибким.
Talk()
Msg("test");
Msg(await Select("Yes", "No"));
Игра вокруг с асинхронным/ждать, я нашел свою единственную проблему в том, что сценарии не так просто, как отправка некоторых сообщений. При вызове других функций из основной функции Talk я должен их ждать, так как выполнение не останавливается иначе. Другие функции могут также вызвать еще больше, создавая неизвестное количество ожиданий.
Talk()
Msg("test");
await OtherTalk();
Msg("end"); // would be called right away
OtherTalk()
Msg("test2");
Msg(await Select("Yes", "No"));
Если я закрываю NPC внутри такого метода «к югу от разговора» Я бы потенциально оставить немало задач висит в воздухе, потому что не будет возвращаться вверх по цепочке. NPC закрыт, больше нет ответов, задачи ждут.
Решение этой проблемы будет возвращаться в цепочку с явными проверками после ожидания такой функции, чтобы проверить, был ли NPC закрыт где-то по линии. Но я хочу, чтобы они были такими же простыми и прямыми, насколько это возможно, и, честно говоря, иметь, если после каждого вызова функции будет слишком утомительно для моего вкуса. Серверное программное обеспечение также будет использоваться новичками, которые могут забыть такую проверку, что может привести к проблемам, в зависимости от того, что делает скрипт.
Мой вопрос сейчас, если кто-то может подумать о способе отмены Заданий, без явных проверок в самих скриптах.
Используйте встроенные функции отмены TPL; см. «CancellationTokenSource». – SLaks
Это потребует проверки в сценариях, потому что задачи будут возвращены, а «родительские» функции не должны продолжать выполнение. – Mars
Нет; ожидание отмененной задачи также отменит вызывающего абонента. Вам просто нужен периодический вызов token.ThrowIfCancellationRequested(). – SLaks