Я пишу многопользовательский игровой сервер и смотрю, как новые функции С# async/await могут Помоги мне. Ядром сервера является цикл, который обновляет всех участников в игре так же быстро, как и могут:
while (!shutdown)
{
foreach (var actor in actors)
actor.Update();
// Send and receive pending network messages
// Various other system maintenance
}
Этот цикл необходим для обработки тысяч участников и обновления несколько раз в секунду, чтобы сохранить игра работает гладко. Некоторые участники иногда выполняют медленные задачи в своих функциях обновления, таких как как выборка данных из базы данных, где я хотел бы использовать async. После получения этих данных актер хочет обновить состояние игры, которое должно быть выполнено в основном потоке.
Как это консольное приложение, я планирую написать SynchronizationContext, который может отправлять ожидающих делегатов в основной цикл. Это позволяет этим задачам обновлять игру после завершения и позволяет исключить необработанные исключения в основной цикл. Мой вопрос: как написать асинхронный функции обновления? Это работает очень хорошо, но нарушает рекомендации не использовать async void:
Thing foo;
public override void Update()
{
foo.DoThings();
if (someCondition) {
UpdateAsync();
}
}
async void UpdateAsync()
{
// Get data, but let the server continue in the mean time
var newFoo = await GetFooFromDatabase();
// Now back on the main thread, update game state
this.foo = newFoo;
}
Я мог бы сделать update() async и протаить задачи обратно в основной цикл, но:
- Я не хочу добавлять накладные расходы на тысячи обновлений, которые никогда не будут использовать его.
- Даже в основном цикле я не хочу ждать задач и блокировать цикл.
- Ожидание задачи приведет к тупиковой ситуации, так как она должна завершиться в ожидающем потоке.
Что мне делать со всеми этими задачами, которые я не могу ждать? Единственный раз, когда мне захочется узнать, что они все завершено, когда я закрываю сервер, но я не хочу собирать каждую задачу, созданную возможно, недели обновлений.