多线程任务执行异常:UI与后台线程交互RPC_E_WRONG_THREAD报错解决
解决跨线程操作UI的RPC_E_WRONG_THREAD异常
这个错误的原因很明确:后台线程无法直接操作UI元素。UWP的UI控件是线程绑定的,只能由创建它们的主线程(UI线程)访问和修改,而你的Task_Completed回调是在后台线程触发的,后续调用TriMessage时直接创建ExtendedSplash对象、调用UI相关方法,就会触发跨线程访问的异常。
解决方案:使用Dispatcher切换到UI线程执行操作
UWP提供了CoreDispatcher来实现线程切换,它可以把UI相关的操作委托到主线程的消息队列中执行。有两种常见的实现方式,你可以根据自己的代码结构选择:
方式1:在TriMessage中仅对UI操作做线程切换
修改TriMessage方法,把创建ExtendedSplash和调用解锁方法的逻辑放到Dispatcher的异步调用里:
public void TriMessage(object data) { switch (data.ToString()) { case "Test": Debug.WriteLine("OK Fonctionne."); break; case "start": Debug.WriteLine("Dévérouillage de l'application"); // 切换到UI线程执行UI操作 Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync( Windows.UI.Core.CoreDispatcherPriority.Normal, () => { // 这里的代码会在UI线程执行,安全操作UI ExtendedSplash UnlockScreen = new ExtendedSplash(splash, state); UnlockScreen.DismissExtendedSplash(); }); break; } }
方式2:在Task_Completed阶段就切换到UI线程
如果后续TriMessage里还有其他UI相关操作,也可以直接在回调触发时就切换到UI线程,这样整个消息处理逻辑都在主线程执行:
private void Task_Completed(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args) { var taskName = sender.Name; Debug.WriteLine(taskName); var localSettingsData = ApplicationData.Current.LocalSettings; try { args.CheckResult(); Object value = localSettingsData.Values["data"]; if (value == null) { Debug.WriteLine("Aucune donnée."); } else { Debug.WriteLine("Donnée trouvée."); // 先切换到UI线程,再处理消息 Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync( Windows.UI.Core.CoreDispatcherPriority.Normal, () => { RecptData.TriMessage(value); }); } } catch (Exception e) { Debug.WriteLine("Erreur OnTaskCompleted : " + e); } }
关键说明
CoreApplication.MainView.CoreWindow.Dispatcher是获取主线程Dispatcher的可靠方式,确保你能切换到正确的UI线程。CoreDispatcherPriority.Normal表示使用普通优先级执行委托,你也可以根据需求选择High等其他优先级。- 所有涉及创建UI控件、修改UI属性、调用UI方法的逻辑,都必须放到Dispatcher的委托中执行,避免跨线程访问。
内容的提问来源于stack exchange,提问作者ValentinDP
相关产品推荐
相关产品推荐

