C# 如何在wpf中按顺序从子窗口更新父UI窗口的标签控件?

C# 如何在wpf中按顺序从子窗口更新父UI窗口的标签控件?,c#,wpf,dispatcher,C#,Wpf,Dispatcher,我试图找出答案,但没有找到真正的答案。有人能回答以下问题吗?我试图通过调用Dispatcher方法来更新父窗口中的状态,但我看到它没有按顺序更新状态。我在主窗口中看到状态更新,如下所示: 第一个进程已启动。。。 第一道工序完成了! 第三道工序完成了 除了UpdateStatus之间的延迟之外,还可以使用其他方法或任务。那么,为什么它不更新其他状态呢?有真实的答案吗 private void Button_Click(object sender, RoutedEventArgs e)

我试图找出答案,但没有找到真正的答案。有人能回答以下问题吗?我试图通过调用Dispatcher方法来更新父窗口中的状态,但我看到它没有按顺序更新状态。我在主窗口中看到状态更新,如下所示:

第一个进程已启动。。。 第一道工序完成了! 第三道工序完成了

除了UpdateStatus之间的延迟之外,还可以使用其他方法或任务。那么,为什么它不更新其他状态呢?有真实的答案吗

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        UpdateStatus("First Process started...");
        Thread.Sleep(5000); //or any method
        UpdateStatus("First Process done!");

        Thread.Sleep(5000); //or any method

        UpdateStatus("Second Process started...");
        Thread.Sleep(5000); //or any method
        UpdateStatus("Second Process done!");

        Thread.Sleep(5000); //or any method

        UpdateStatus("Third Process started...");
        Thread.Sleep(5000); //or any method
        UpdateStatus("Third Process done!");
    }

    private void UpdateStatus(string message)
    {
        Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate
        {
            MainWindow.main.lblTest.Content = message;
        }
        ));
    }

单个线程不能同时更新UI和睡眠

您可以在状态更新之间异步等待,但:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    UpdateStatus("First Process started...");
    await Task.Delay(5000);
    UpdateStatus("First Process done!");

    await Task.Delay(5000);

    UpdateStatus("Second Process started...");
    await Task.Delay(5000);
    UpdateStatus("Second Process done!");

    await Task.Delay(5000);

    UpdateStatus("Third Process started...");
    await Task.Delay(5000);
    UpdateStatus("Third Process done!");
}

private void UpdateStatus(string message)
{
    MainWindow.main.lblTest.Content = message;
}

您正在UI线程中同步运行所有内容,在完成之前阻止任何调用(因此不进行更新,然后一次执行所有更新)。只需在任务中移动代码:

void Button_Click(object sender, RoutedEventArgs e) => Task.Run(() =>
{
     ... // rest of your code
});
你们应该很好(除非你们按两次按钮,但我想这很容易解决)

顺便说一句,您还可以使用另一个invoke重载:

Dispatcher.Invoke(() => lblTest.Content = message);

我希望这将使情况更加清楚

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        // I run on the main thread and return immediately
        await SearchForAliensAsync();
    }

    private async Task SearchForAliensAsync()
    {
        // I run on (capture) the caller thread (main thread)
        UpdateStatus("Searching for aliens...");

        /* Dispatch the dirty work on a background thread and return immediately,
         * so that the caller thread (main thread) remains responsive.
         * If you don't do that, the main thread will get blocked.
         * From the user perspective the UI is frozen.
         * The main thread will search infinitely for aliens,
         * instead of doing its main job - poping and dispatching messages from
         * its message queue (Win32 is event driven).
         * The operating system will keep notifying the main thread,
         * that the user has clicked on the window or smashed multiple keys on the keyboard,
         * but the main thread won't listen, it's searching for aliens!
         * The operating system monitors all main threads, by measuring what
         * time has elapsed from the last call to GetMessage(...) and
         * if the latter exceeds a certain amount, it will play a trick on you.
         * The OS will create a transparent window and place it on top of the 
         * unresponsive one, so that it can detect the next angry mouse click
         * and display the famous "Application is not responding" dialog...
         */
        await Task.Run(() =>
        {
            // I run synchronously on the thread pool and I won't finish any time soon..
            SearchForAliens();
        });

        // When my time comes, I'll be dispatched on the captured thread (main thread)
        UpdateStatus("Aliens exist!");
    }

谢谢你的评论。但是,如果有任何方法可以代替延迟,那么它将如何工作呢?那么您需要在后台线程上实际执行一些长时间运行的工作。否则,“第三个过程完成!”状态确实会立即显示。如果该方法需要1或2分钟,则可以轻松查看状态更改。我如何才能阻止那个时间,使状态不能立即更新?但我不知道我的方法将运行多长时间。若我给任务延迟50秒,方法运行110秒,那个么它可能不起作用。我猜。你在说什么方法?你在最初的问题中没有提到任何问题。如前所述,如果你有其他问题,请问一个新问题。如果您确实想使用sleep,那么@mm8(
async/await
)的解决方案会更好,尽管在这种情况下我只会使用计时器和消息集合。我已经考虑了同步方法,再次考虑了异步方法-使用
async/await
方法。