【问题标题】:UWP - How Can Dispatcher DispatchedHandler Run On Worker Thread?UWP - Dispatcher DispatchedHandler 如何在工作线程上运行?
【发布时间】:2018-09-17 17:40:05
【问题描述】:

我正在尝试通过调度程序从后台线程更新一些 UWP UI。 但是,传递给 RunAsync 方法的处理程序仍在后台线程上执行。

我不知道如何解决这个问题 - 我错过了什么吗?

--编辑--

我只有一个窗口,即Window.Current

我已经尝试了 Community Toolkit DispatcherHelper 类,但我仍然得到完全相同的异常

private static async void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var panel = (SidePanelInfo) d;
    var x = e.NewValue as TaskItemViewModel;
    await DispatcherHelper.ExecuteOnUIThreadAsync(() =>
    {
        panel.DescriptionBox.Document.SetText(TextSetOptions.FormatRtf, x?.Description ?? "");
    });

}

【问题讨论】:

  • 您是否尝试过在没有调度程序的情况下设置文本?
  • 是的。我添加了调度程序调用来尝试修复,因为这看起来像是所有 XAML 控件共有的跨线程异常
  • 我查看了实时可视化树,肯定只有 1 个窗口。既然我知道没有一个直截了当的答案,我自己会更深入地研究这个问题。感谢您的帮助
  • 好的 - 这是意料之外的。我一直工作回到 App.xaml.cs 中的构造函数,并从后台线程调用它。那是最出乎意料的。然后将所有 Windows、页面和控件加载到后台线程上。 SelectedItem 是在初始化期间设置的——所有这些都发生在后台线程上。我真的不明白
  • 实际上,每个 UWP 应用都会发生这种情况

标签: xaml uwp


【解决方案1】:

如果您已经在后台线程上,则无法访问 Window.Current.Dispatcher,因为后台线程没有设置 Window.Current(该属性获取与调用它的 UI 线程关联的 Window 实例)。

相反,您应该首先在 UI 线程上检索 Dispatcher 实例,然后使用此实例执行 RunAsync

但是 - OnSelectedItemChanged 看起来更像是一个 UI 事件处理程序,在这种情况下,您不应该要求在 UI 线程上运行代码。例如,当从Button 点击触发时,如果您只是使用相同的参数运行panel.DescriptionBox.Document.SetText,请检查UnauthorizedAccessException 是否不会发生。

多视图和多窗口应用程序

如果您正在创建多视图或多窗口 UWP 应用程序,则可能会出现此问题,因为在 UWP 中每个窗口都有自己的 UI 线程。这意味着当您想要跨窗口更新属性时,您总是需要使用目标窗口/应用程序视图的Dispatcher

【讨论】:

  • 不可能这样做,因为这是一个已经在后台线程上的依赖属性 propertychangedcallback
  • 你不应该首先修改非 UI 线程上的依赖属性 - 在设置依赖属性本身时最好使用调度程序。
  • 我不明白依赖回调是如何在后台线程上运行的
  • Martin - 发现了问题,与线程无关(见我的回答)。感谢您的帮助,如果浪费了您的时间,我们深表歉意
  • 哇,这是一个非常有趣的发现:-D。我永远不会想到这可能是问题所在。但很高兴你设法解决它:-)。编码愉快!
【解决方案2】:
WindowsCommunityToolkit 中的

DispatcherHelper 在这里会很有帮助。

它使您可以选择在 UI 线程上执行代码或在 MainView 上执行代码(如果您有多个窗口)

DispatcherHelper.ExecuteOnUIThreadAsync<T>(() =>
{
    // Code to execute on main window's UI thread
});

await CoreApplication.MainView.Dispatcher.AwaitableRunAsync<T>( () =>
{

});

【讨论】:

    【解决方案3】:

    好的,我终于知道发生了什么事,这不是我所期望的。

    该问题与线程或调度程序无关,尽管调度程序在工作线程上执行(UWP 调度程序似乎不像 WPF 那样在主线程上运行),并且尽管错误与您的错误相同期待您是否有跨线程 UI 异常。

    原来我有一个 RichEditBox 无意中处于只读模式。因为这个控件不支持绑定到它的内容,所以我在代码隐藏中设置了内容。例外是因为我在控件处于只读模式时设置了它的文本。

    很遗憾,即使在只读模式下,控件也无法给出更有意义的错误,或者无法以编程方式进行编辑 - 就像 WPF 等效项一样。但是你去。希望这个问答页面能帮助遇到同样问题的其他人。

    非常感谢 Martin Zikmund 在我确定这是调度问题时尝试帮助我。

    【讨论】:

      猜你喜欢
      • 2015-08-23
      • 1970-01-01
      • 2021-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-02
      • 1970-01-01
      相关资源
      最近更新 更多