1

在第二种方法(DoWork)退出之前,以下方法不会应用 wpf 更改(背景 = 红色):

private void change()
{
    Background = Brushes.Red;
    Dispatcher.BeginInvoke((Action) DoWork);
}

DoWork() 需要几秒钟才能运行,我真的不想将它放入线程中,因为此代码将在多个地方使用,并且可能会以不同的时间间隔与 Dispatcher 线程交互。我试过调用 Invalidate...() 方法,但无济于事。添加了 BeginInvoke() 以查看延迟是否允许在调用逻辑之前应用背景更改。通常,逻辑将是此方法的一部分。顺便说一句,大部分逻辑都是在不同的线程上执行的,不应该阻塞 Dispatcher 线程?!

有人可以帮忙吗?谢谢

4

3 回答 3

3

“Dispatcher”线程是 UI 线程。

当您调用 时Dispatcher.BeginInvoke((Action) DoWork);,您基本上会阻塞 UI 线程直到DoWork退出,因为它在 UI 线程上运行。

这将阻止 UI 更新,因此您看不到背景更改。

您确实应该考虑DoWork直接通过 ThreadPool、BackgroundWorker 或其他方式转移到后台线程。这将完全纠正此问题,并防止您在“几秒钟”内阻塞 UI 线程(如果您使用 Dispatcher 的线程运行它,则会发生这种情况)。

于 2010-04-13T16:21:27.517 回答
0

对于线程之间的通信,我们有DispatcherWPF 中的类。

Dispatcher.Invoke(DispatcherPriority.Normal, (NoArgDelegate)delegate
            {
                ------
            });
于 2010-05-20T23:30:43.117 回答
0

BeginInvoke(..) 方法不会阻塞调用,它只是将一条新消息放入队列以由调度程序线程处理。在您发布的代码中,您无法保证在 DoWorks 启动之前会处理背景颜色更改。

您可以降低 DoWork 调用的优先级,以确保首先更改背景:

        private void Button_Click(object sender, RoutedEventArgs e)
    {
        grid.Background = new SolidColorBrush(Colors.Red);
        Dispatcher.BeginInvoke((Action)DoWork, DispatcherPriority.ContextIdle);
    }

    private void DoWork()
    {
        Thread.Sleep(1000);
        btn.Content = "Done";
    }

但这并不是人类已知的最佳解决方案。

最好在单独的线程中继续使用 DoWork。上面使用线程方法的示例将如下所示:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        grid.Background = new SolidColorBrush(Colors.Red);

        Task t = new Task(DoWork);
        t.Start();
    }

    private void DoWork()
    {
        Thread.Sleep(1000);
        // Synchronize calls to the UI elements
        Application.Current.Dispatcher.BeginInvoke((Action)(() => { btn.Content = "Done"; }));

    }

只需记住将 UI 元素上的所有操作发布到 UI 线程即可。

于 2012-12-22T13:17:59.340 回答