I have since found an even easier method, but please use it with caution.
If you want to still use the UObject system and use dynamic multicast style delegates within an async task on the game thread you may disable to script guard (at least in the Editor) to perform such a task.
void SomeClass::BeginDisconnection()
{
OnDisconnectProcedureStarted.Broadcast();
AsyncTask(ENamedThreads::AnyNormalThreadHiPriTask, [=]()
{
API::Logout();
// Multicast dynamic delegates must be called from the game thread!
AsyncTask(ENamedThreads::GameThread, [=]()
{
#if WITH_EDITOR
TGuardValue<bool> AutoRestore(GAllowActorScriptExecutionInEditor, true);
#endif
OnDisconnectProcedureComplete.Broadcast(false);
});
});
}
Notice how in editor you can scope the script guard value that prevents delegates bound in UObjects in blueprints from being called. This at least worked for me in these cases.
It is a bit awkward running yet another async task back on the game thread, but I think it’s still a fairly elegant in-line solution.