在WPF的主UI线程中,如果有一个计算量较大的过程,会阻塞UI线程,造成界面卡顿且不会刷新。
效果图如下,整个过程花费了12秒,界面没有卡顿。
1. 网上搜索了以下方法:
/// <summary>
/// 强制刷新界面
/// </summary>
public partial class App : System.Windows.Application
{
private static DispatcherOperationCallback exitFrameCallback = new DispatcherOperationCallback(ExitFrame);
public static void DoEvents()
{
DispatcherFrame nestedFrame = new DispatcherFrame();
DispatcherOperation exitOperation = Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, exitFrameCallback, nestedFrame);
Dispatcher.PushFrame(nestedFrame);
if (exitOperation.Status !=
DispatcherOperationStatus.Completed)
{
exitOperation.Abort();
}
}
private static Object ExitFrame(Object state)
{
DispatcherFrame frame = state as
DispatcherFrame;
frame.Continue = false;
return null;
}
}
在需要刷新的地方,调用 App.DoEvents();
似乎效果并不理想,没有达到我要的效果。
2. 新开一个线程来处理
以下是button事件里的内容,Thread_One事件是一个耗时过程,包含大量计算过程。
vm.SbInformation = "反演进行中,请耐心等待······";
sbInfo.Foreground = Brushes.Black;
vm.IsRunning = true;
// 新开一个线程用于反演
Thread thread = new Thread(Thread_One)
{
IsBackground = true
};
thread.Start();
void Thread_One()
{
DateTime dt1 = DateTime.Now;
CNMInverter2D DemoInverter = new CNMInverter2D(demoParams);
DemoInverter.RUN(); // 这个过程消耗大量时间
DateTime dt2 = DateTime.Now;
TimeSpan timespan = dt2.Subtract(dt1);
// 界面更新相关的东西参考以下方式
Dispatcher.BeginInvoke(DispatcherPriority.Normal,
(ThreadStart)delegate ()
{
Result_Draw(0); // 绘图
tabControl.SelectedIndex = 1; // 切换到反演曲线页面
vm.SbInformation = "反演完成!" + "反演耗时:" + string.Format("{0:F3}", timespan.TotalSeconds) + "(s)";
sbInfo.Foreground = Brushes.Red;
vm.IsRunning = false;
}
);
}