【问题标题】:Are WPF DataBindings not refreshed on Dispatcher.Yied()?是否在 Dispatcher.Yield() 上未刷新 WPF 数据绑定?
【发布时间】:2021-06-11 17:47:30
【问题描述】:

所以,我有一个大型应用程序,它在 UI 线程上做了一些长时间的工作。我知道这是糟糕的设计,但这是无法改变的。把它当作一个约束。

为了显示工作的进度,我想显示一个带有进度条的 WPF 对话框。该对话框将 DataBindings 用于 DependencyProperties 的标签和进度条。

当我第一次在对话框实例上调用Show() 时,对话框不会显示,因为调度程序正忙于处理长时间运行的任务。所以我在Show() 之后打电话给Dispatcher.Yield()。每次更新进度条的 DependencyProperty 后,我也会调用 Yield()。对话窗口出现了,但它仍然很空。 Dispatcher.Yield() 上的 DataBindings 未更新。

有没有机会在 Dispatcher 忙时让他们更新?

示例应用

创建一个新的 .NET Framework WPF 应用,将其命名为“BusyProgress”并更改这些文件。

MainWindow.xaml

<Window x:Class="BusyProgress.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="clr-namespace:BusyProgress"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        x:Name="window"
        Title="MainWindow"
        Width="400"
        Height="100"
        mc:Ignorable="d">
    <DockPanel DataContext="{Binding ElementName=window}">
        <ProgressBar Height="20"
                     DockPanel.Dock="Bottom"
                     Maximum="10"
                     Value="{Binding Progress}" />
        <TextBlock Text="{Binding LabelText}" />
    </DockPanel>
</Window>

MainWindow.xaml.cs

using System.Windows;

namespace BusyProgress
{
    public partial class MainWindow : Window
    {
        public string LabelText
        {
            get => (string)GetValue(LabelTextProperty);
            set => SetValue(LabelTextProperty, value);
        }
        public static readonly DependencyProperty LabelTextProperty =
            DependencyProperty.Register("LabelText", typeof(string), typeof(MainWindow), new PropertyMetadata("Initial Value"));

        public int Progress
        {
            get => (int)GetValue(ProgressProperty);
            set => SetValue(ProgressProperty, value);
        }
        public static readonly DependencyProperty ProgressProperty =
            DependencyProperty.Register("Progress", typeof(int), typeof(MainWindow), new PropertyMetadata(0));

        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

App.xaml

<Application x:Class="BusyProgress.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Startup="Application_Startup" />

App.xaml.cs

using System.Windows;
using System.Windows.Threading;
using System.Threading;
using System;

namespace BusyProgress
{
    public partial class App : Application
    {
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            MainWindow window = new MainWindow();
            window.LabelText = "Init";
            window.Show();
            Dispatcher.Yield();

            // Do some long running stuff
            int count = 0;
            while (count++ < 10)
            {
                Console.WriteLine(count);
                window.Progress = count;
                window.LabelText = $"Working hard... ({count}/10)";
                Dispatcher.Yield();

                // Simulate Work
                Thread.Sleep(500);
            }

            MessageBox.Show("Done");
        }
    }
}

【问题讨论】:

  • 调度程序队列是优先队列。它将首先运行具有较高优先级的任务,而较低优先级(包括绑定更新 afaik)将没有机会运行。您可以尝试使用 in this answer 之类的东西来打破您的 UI 占用任务:调用足够低的优先级以确保绑定将得到更新。
  • 感谢您的意见。 Dispatcher.Yield(DispatcherPriority.SystemIdle) 不应该在调度程序上运行最低优先级的任务吗?我只是觉得我缺少一些禁用 DataBindings 的框架方法或属性......也许其他人知道它 =)
  • 我没有使用Dispatcher.Yield 的经验。试试我之前评论的建议。此外,您应该在遇到问题时显示minimal reproducible example,这可能不是我们目前怀疑的Dispatcher.Yield
  • 我刚试过这个,但它仍然没有更新绑定。当我跳过Hide() 调用我的对话框并让UI线程上的长时间运行任务完成时,对话框将更新并显示最后一个状态......所以我猜biniding被正确定义但只是没有更新而用户界面很忙...
  • 是的,你是对的。我很快就会准备一个例子

标签: c# wpf data-binding dispatcher


【解决方案1】:

构建示例有助于认识到this answer 实际上就足够了。
我的应用程序有另一个我以前没有意识到的限制。 Dispatcher 已禁用 -.-...感谢 sintar 的帮助!

【讨论】:

    猜你喜欢
    • 2010-10-13
    • 1970-01-01
    • 2011-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多