Unreal Engine中C++/WinRT异步函数Delegate Broadcast崩溃问题求助
Unreal Engine中C++/WinRT异步语音识别触发多播委托崩溃的解决方法
问题核心
WinRT语音识别的异步回调运行在非UE游戏线程,而UE的UObject(包括多播委托)仅允许在游戏主线程操作,跨线程直接调用委托广播会触发线程安全检查崩溃——这就是同步调用正常、异步调用崩溃的根本原因。
解决步骤
1. 将委托广播切换到UE主线程执行
在WinRT的异步识别回调中,不要直接调用Broadcast(),而是通过UE的线程调度工具把广播逻辑投递到主线程:
// VoiceRecog.cpp 中异步回调内的代码替换 FString RecognizedText = ...; // 识别到的文本 AsyncTask(ENamedThreads::GameThread, [this, RecognizedText]() { // 在主线程安全执行委托广播 OnTextRecognized.Broadcast(RecognizedText); });
WinRT的语音识别回调默认跑在系统线程池,不属于UE游戏线程,通过AsyncTask转主线程即可规避线程冲突。
2. 增加对象有效性检查
广播前确认当前UObject及绑定的Widget未被销毁,避免访问无效内存:
AsyncTask(ENamedThreads::GameThread, [this, RecognizedText]() { if (this->IsValidLowLevel()) // 检查当前语音识别对象是否有效 { OnTextRecognized.Broadcast(RecognizedText); } });
3. 管理WinRT异步会话生命周期
在UObject销毁时,及时停止WinRT语音识别会话并释放资源,避免回调在对象销毁后触发:
void UVoiceRecog::BeginDestroy() { if (SpeechRecognizer != nullptr) { SpeechRecognizer.StopRecognitionAsync().get(); SpeechRecognizer = nullptr; } Super::BeginDestroy(); }
4. 可选:声明线程安全委托(非必须)
如果需要委托支持跨线程触发(仍建议主线程操作UObject),可以声明线程安全类型的多播委托:
// VoiceRecog.h 中委托声明 DECLARE_THREADSAFE_MULTICAST_DELEGATE_OneParam(FOnTextRecognized, FString);
验证方法
修改后重新编译项目,测试语音识别功能,此时委托广播会在主线程安全执行,蓝图Widget可正常接收并显示识别文本,不会再出现崩溃。
内容的提问来源于stack exchange,提问作者Steven Yen
相关产品推荐
相关产品推荐

