Raising asynchronous events not working
FabianNitsche opened this issue · 1 comments
Thank you for implementing this port! Great work!
I tried to compile and run it. However, when I start a new game. I got window with the graphics and all but my character is basically in the middle of the Toronto Map and the NPCs are not moving and no music nor sound was playing.
I was debugging the problem and found that the game works up to the commit on the 11th of January 2024. After that, More async calls are introduced to e.g. GameState.InitialiseGame().
await RaiseAsync(new LoadMapEvent(_game.MapId);
Any code below this line is not called. Because of this, The fast clock is not started - so no NPC will move etc.
Basically, the await does not complete.
I was debugging a little further and found, that adding the follwoing lines to in EventExchange.RaiseAInvoker(...) helps:
if (core != null && core.OutstandingCompletions == 0)
core.SetResult(Unit.V);
so that it looks like:
static AlbionTask<Unit> RaiseAInvoker(List<Handler> handlers, IEvent e, object sender, int _) // Waits for all handlers to complete
{
AlbionTaskCore<Unit> core = null;
foreach (var handler in handlers)
{
if (sender == handler.Component) continue;
switch (handler)
{
case ISyncHandler syncHandler:
syncHandler.Invoke(e);
break;
case IAsyncHandler asyncHandler:
core ??= new($"RaiseAInvoker helper for {e.GetType()} from {sender}");
var innerTask = asyncHandler.InvokeAsAsync(e);
if (!innerTask.IsCompleted)
{
core.OutstandingCompletions++;
var core1 = core;
innerTask.OnCompleted(() =>
{
core1.OutstandingCompletions--;
if (core1.OutstandingCompletions == 0)
core1.SetResult(Unit.V);
});
}
break;
default:
throw new InvalidOperationException($"Could not invoke handler {handler}");
}
}
if (core != null && core.OutstandingCompletions == 0)
core.SetResult(Unit.V);
return core?.Task ?? AlbionTask.Unit;
}
This is probably not a solution. But I hope it helps you to spot the issue.
I am happy to help and investigate further, but this is my first experience with custom made async + events... :D
Thanks for investigating! I'd been meaning to look into this bug, but had been working on some other things. The fix will indeed be to call core.SetResult(Unit.V), but it'll be better to do it when the asyncHandler returns a completed task rather than in the outer scope. I've submitted this fix now.