简体   繁体   English

如何在wpf中以顺序方式从子窗口更新父UI窗口的标签控件?

[英]How to update label control of the parent UI window from child window in sequential manner in wpf?

I have tried to find out the answer but no real answer found.我试图找出答案,但没有找到真正的答案。 Can anyone answer following?有人可以回答以下吗? I am trying to update status in the parent window by calling Dispatcher Method, but I see it does not update the status in sequential manner.我试图通过调用 Dispatcher Method 来更新父窗口中的状态,但我看到它没有按顺序更新状态。 I see the status update in the mainwindow as follow:我在主窗口中看到状态更新如下:

First process started... First Process done!第一个过程开始... 第一个过程完成! Third Process done!第三道工序完成!

Instead of delay between the UpdateStatus, there can be some other method or task.除了 UpdateStatus 之间的延迟,还可以有其他一些方法或任务。 So, Why it does not update other status?那么,为什么它不更新其他状态? Any real answer please?请问有真正的答案吗?

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

A single thread can't both update the UI and sleep at the same time.单个线程不能同时更新 UI 和休眠。

You could wait asynchronously between the status updates though:不过,您可以在状态更新之间异步等待:

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;
}

I hope this will make it more clear.我希望这会让它更清楚。

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

You are running everything synchronously in UI thread, preventing any invoke until you finish (therefore no updates and then all updates at once).您在 UI 线程中同步运行所有内容,在完成之前防止任何调用(因此没有更新,然后所有更新一次)。 Simply move your code in task:只需在任务中移动您的代码:

void Button_Click(object sender, RoutedEventArgs e) => Task.Run(() =>
{
     ... // rest of your code
});

and you should be fine (fine unless you press button twice, but that's easy to fix I guess).你应该没问题(除非你按两次按钮,否则我猜这很容易解决)。

Btw, you can also use another overload of invoke:顺便说一句,您还可以使用另一个调用重载:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM