WPF屏幕冻结使用Dispatcher BeginInvoke方法

问题描述 投票:1回答:1

我有一个问题与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);
            });

    }

循环继续时屏幕冻结。我想在后面进行循环工作,屏幕仍然可以使用直到完成。为什么会这样,我该如何解决这个问题?

c# wpf multithreading freeze dispatcher
1个回答
2
投票

当你“调用一个线程”时,你告诉那个线程停止正在做的事情并改为执行你的代码。

因此,您正在启动一个线程,该线程会在其完成所有工作时立即阻止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更新之间的间隔时间更长?如果我实现的是一个只在TextBlock中显示递增整数的线程,我会在Invoke之外的循环中放置一个Thread.Sleep(250)。为UI提供响应用户输入的机会。

或者,好多了,因为这是WPF,编写一个viewmodel并通过绑定更新txtCount.Text,它将为您执行调用。你甚至不必考虑调度员。

© www.soinside.com 2019 - 2024. All rights reserved.