我正在创建一个包含一系列事件的类,其中一个是GameShuttingDown
。触发此事件后,我需要调用事件处理程序。该事件的目的是通知用户游戏正在关闭,他们需要保存其数据。可以等待保存,而不能等待事件。因此,当处理程序被调用时,游戏将在等待的处理程序完成之前关闭。
public event EventHandler<EventArgs> GameShuttingDown;
public virtual async Task ShutdownGame()
{
await this.NotifyGameShuttingDown();
await this.SaveWorlds();
this.NotifyGameShutDown();
}
private async Task SaveWorlds()
{
foreach (DefaultWorld world in this.Worlds)
{
await this.worldService.SaveWorld(world);
}
}
protected virtual void NotifyGameShuttingDown()
{
var handler = this.GameShuttingDown;
if (handler == null)
{
return;
}
handler(this, new EventArgs());
}
活动注册
// The game gets shut down before this completes because of the nature of how events work
DefaultGame.GameShuttingDown += async (sender, args) => await this.repo.Save(blah);
我知道事件的签名是正确的void EventName
,因此使它异步基本上是生死攸关的。我的引擎大量使用事件通知第三者开发人员(和多个内部组件)事件正在引擎内发生,并让事件对事件做出反应。
有没有什么好的方法可以将事件替换为我可以使用的基于异步的东西?我不确定是否应该使用回调BeginShutdownGame
并EndShutdownGame
与之配合使用,但这很痛苦,因为只有调用源才能传递回调,而没有任何第三者插件可以插入引擎,这就是我从事件中获得的东西。如果服务器调用game.ShutdownGame()
,则引擎插件和引擎中的其他组件无法传递其回调,除非我采用某种注册方法,并保留了一系列回调。
任何关于采用哪种首选/推荐路线的建议都将不胜感激!我环顾四周,大部分情况下我所看到的是使用Begin / End方法,我认为这不会满足我想要做的事情。
编辑
我正在考虑的另一个选项是使用注册方法,该方法需要等待回调。我遍历所有回调,抓住它们的Task并等待一个WhenAll
。
private List<Func<Task>> ShutdownCallbacks = new List<Func<Task>>();
public void RegisterShutdownCallback(Func<Task> callback)
{
this.ShutdownCallbacks.Add(callback);
}
public async Task Shutdown()
{
var callbackTasks = new List<Task>();
foreach(var callback in this.ShutdownCallbacks)
{
callbackTasks.Add(callback());
}
await Task.WhenAll(callbackTasks);
}