UWP中使用await Task.Run()抛出RPC_E_WRONG_THREAD异常的解决问询
解决UWP中Task.Run创建TextHighlighter时的RPC_E_WRONG_THREAD异常
嘿,你这个问题我太熟了——这是UWP线程模型的经典坑!咱们先把问题根源说清楚:
- 第一个
Task.Run能正常工作,是因为DoStuffAsync只做了字符串查找和列表计算,完全不碰任何UI相关的对象,后台线程可以安全执行这些纯数据操作。 - 第二个
Task.Run报错,是因为CreateHighlighter里创建了TextHighlighter、SolidColorBrush这些UI专属对象。UWP有个硬性规则:所有UI元素的创建、修改必须在UI线程上进行,后台线程碰这些对象就会触发RPC_E_WRONG_THREAD异常。
最简单的解决方案
其实CreateHighlighter里的逻辑非常轻量(只是循环添加几个TextRange),根本不需要放到后台线程跑,直接在UI线程执行就行,完全不会卡界面。
修改后的代码
首先调整btnFind_Click方法,去掉第二个多余的Task.Run:
private async void btnFind_Click(object sender, RoutedEventArgs e) { string tofind = txbToFind.Text.ToLower(); string completeText = string.Empty; for (int a = 0; a <= TextOneRich.Blocks.Count - 1; a++) { Paragraph paragraphCurrent = TextOneRich.Blocks[a] as Paragraph; for (int b = 0; b <= paragraphCurrent.Inlines.Count - 1; b++) { completeText += (paragraphCurrent.Inlines[b] as Run).Text; } } // 字符串查找是CPU密集操作,继续用Task.Run放后台避免卡UI List<int> indexList = await Task.Run(() => DoStuffAsync(completeText, tofind)); // 直接在UI线程创建TextHighlighter,不用再包Task.Run TextHighlighter HighlighterAll = CreateHighlighter(indexList, tofind.Length); TextOneRich.TextHighlighters.Clear(); TextOneRich.TextHighlighters.Add(HighlighterAll); }
然后把CreateHighlighter改成同步方法(因为它本来就没有真正的异步操作,之前的async/await是多余的):
private TextHighlighter CreateHighlighter(List<int> listaindex, int length) { TextHighlighter highlighter = new TextHighlighter() { Foreground = new SolidColorBrush(Colors.White), Background = new SolidColorBrush(Color.FromArgb(255, 7, 58, 77)) }; foreach (int index in listaindex) { highlighter.Ranges.Add(new TextRange() { StartIndex = index, Length = length }); } return highlighter; }
扩展场景:如果必须后台计算再创建UI?
要是以后你碰到需要先在后台做 heavy 计算,再创建UI对象的场景,可以用Dispatcher.RunAsync切回UI线程操作:
// 后台做耗时计算 var computedData = await Task.Run(() => SomeHeavyCalculation()); // 切回UI线程创建UI元素 await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { var highlighter = new TextHighlighter(); // 配置高亮器... TextOneRich.TextHighlighters.Add(highlighter); });
核心规则记牢
UWP开发里一定要记住:UI元素的创建、修改必须在UI线程执行,后台线程只负责纯数据计算、文件IO、网络请求这些非UI的工作,别让后台线程碰任何UI相关的东西!
内容的提问来源于stack exchange,提问作者Jib58
相关产品推荐
相关产品推荐

