【问题标题】:WPF screen freeze use Dispatcher BeginInvoke methodsWPF 屏幕冻结使用 Dispatcher BeginInvoke 方法
【发布时间】:2018-01-04 20:13:53
【问题描述】:

我在使用 WPF 时遇到了循环和冻结屏幕的问题。 我的示例代码在这里

private void Btn1_OnClick(object sender, RoutedEventArgs e)
    {            
        ThreadPool.QueueUserWorkItem(
            o =>
            {
                FaturaCount.Dispatcher.InvokeAsync(() =>
                {
                    int a = 0;
                    for (int i = 0; i < 10000000000; i++)
                    {
                        a = a + i;
                    }
                    txtCount.Text = a.ToString();
                }, DispatcherPriority.Background);
            });

    }

在循环继续时屏幕冻结。 我想让循环在后面工作,并且屏幕仍然可以使用,直到它完成。 为什么会发生,我该如何解决?

【问题讨论】:

  • 您正在启动一个线程,然后在 UI 线程中完成所有工作。无需将整个循环放入 Invoke lambda 中,只需调用您需要触摸 UI 的一小部分 - 或者,更好的是,编写一个视图模型并通过绑定更新 txtCount.Text,这将为您执行调用,您甚至不必考虑调度程序。
  • 我在线程下方放置了循环,它解决了我的问题。谢谢解答

标签: c# wpf multithreading freeze dispatcher


【解决方案1】:

当您“调用一个线程”时,您是在告诉该线程停止它正在做的任何事情并改为执行您的代码。

因此,您正在启动一个线程,该线程会在 UI 线程在那里完成所有工作时立即阻塞。那不是你的本意。

不要将整个循环放在 Invoke lambda 中,只需调用您需要触摸 UI 的一小部分:

ThreadPool.QueueUserWorkItem(
    o =>
    {
        int a = 0;
        for (int i = 0; i < 10000000000; i++)
        {
            a = a + i;
            FaturaCount.Dispatcher.Invoke(() =>
            {
                txtCount.Text = a.ToString();
            });
        }
    });

显然,上面的代码并没有做任何有用的事情,如此快速重复调用 Invoke 也没有多大意义。这将使 UI 几乎与原始版本一样严重。现代硬件可以非常非常快速地增加整数和迭代循环。这是您的实际代码,还是线程中的循环实际上在做一些更有用的事情,UI 更新之间的间隔更长?如果我正在实现一个只在 TextBlock 中显示递增整数的线程,我会在 Invoke 之外的循环中放置一个 Thread.Sleep(250) 或其他东西。让 UI 有机会响应用户输入。

或者,更好,因为这是 WPF,编写一个视图模型并通过绑定更新txtCount.Text,这将为您执行调用。那时您甚至不必考虑调度程序。

【讨论】:

  • 为文本框安排无限数量的更新将像 OP 的代码一样冻结 UI,假设它不会通过破坏消息泵的容量而使整个程序完全崩溃。
  • @Servy 非常正确。我想我应该向 OP 确认这只是一个简化的示例。
  • 嗨。实际上我正在为这个过程使用视图模型。我简化了代码以便清楚理解感谢您的回答
  • @MuratAras 非常好。很高兴我能帮上忙。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-13
  • 2012-11-04
  • 1970-01-01
  • 2013-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多