Dispatcher.Yied() 上是否没有刷新 WPF DataBindings?

Are WPF DataBindings not refreshed on Dispatcher.Yied()?

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

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

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

上更新

在 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");
        }
    }
}

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