我在使用循环和冻结屏幕时遇到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);
});
}
循环继续时屏幕冻结。 我想在后面进行循环工作,屏幕仍然可以使用直到完成。 为什么会发生这种情况?如何解决这个问题?
答案 0 :(得分:2)
当您&#34;调用线程&#34;时,您告诉该线程停止执行任何操作并执行代码。
因此,您正在启动一个线程,该线程会在其完成所有工作时立即阻止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
,它将为您执行调用。你甚至不必考虑调度员。