我认为之前可能会问过这个问题,但我可能太傻了,无法理解所给出的答案,所以我需要再次提问。
我有一个类对某些数据执行计算。在计算过程中,我想将数据检查,状态更新和数据行的错误通知输出到UI。我想实时做到这一点。从主应用程序中调用它时我遇到的问题是UI(在WPF中)冻结,直到所有计算完成,然后所有消息一次显示。这对于需要20到30秒才能完成的计算来说是个问题。
所以我试图使用线程。这几乎是我第一次尝试这个东西。我正在做类似的事情:
private void btnStartCalculations_Click(object sender, RoutedEventArgs e)
{
//initialise parameters for run
calculator = new Calculator(...);
//Subscribe to calculator events for update
kasenCalculator.OnStatusUpdate += new Calculator.UpdateEventHandler(calculator_OnStatusUpdate);
//kasenCalculator.OnErrorLogUpdate += new Calculator.ErrorLogUpdateEventhandler(calculator_OnErrorLogUpdate);
//kasenCalculator.OnDataReadUpdate += new Calculator.DataReadUpdateEventHandler(calculator_OnDataReadUpdate);
//Run
Thread thread = new Thread(calculator.Run);
thread.Start();
}
private void calculator_OnStatusUpdate(object sender, string Message)
{
Dispatcher.Invoke(DispatcherPriority.Normal, new Action<string>(UpdateStatusWindow), Message);
}
private void calculator_OnDataReadUpdate(object sender, string Message)
{
Dispatcher.Invoke(DispatcherPriority.Normal, new Action<string>(UpdateOriginalDataWindow), Message);
}
private void calculator_OnErrorLogUpdate(object sender, string Message)
{
Dispatcher.Invoke(DispatcherPriority.Normal, new Action<string>(UpdateErrorLog), Message);
}
private void UpdateStatusWindow(string Message)
{
TextBox statusWindow = this.txtStatus;
//Add status text
statusWindow.Text += Message + "\r\n";
//Scroll to bottom of window
statusWindow.CaretIndex = statusWindow.Text.Length;
statusWindow.ScrollToEnd();
}
private void UpdateOriginalDataWindow(string Message)
{
this.txtOriginalData.Text += Message;
}
private void UpdateErrorLog(string Message)
{
this.txtErrors.Text += Message + "\r\n";
}
哪种方式有效,因为用户界面 正在更新,但它仍然不是很敏感。我想知道我是否应该使用BeginInvoke
而不是Invoke
,但这只是保留所有更新,直到计算完成运行,我也可以在主线程中执行。
此外,即使它正在运行,它实际上运行速度比我预期的要慢很多。
这是我正在做的事情的正确方法吗?如果没有,那么正确的方法是什么?
答案 0 :(得分:0)
使用BeginInvoke
对UI线程进行异步调用。您对Invoke
的使用正在阻止。
您的性能问题可能与字符串连接有关。你有很多日志消息吗?
也许使用ItemsControl
并将ObservableCollection<string>
绑定到它。然后只需将您的日志消息添加到该集合
答案 1 :(得分:0)
你正确地做到了。如果重要的是使Dispatcher的优先级更高......
UpdateLayout();
这将强制您的UI重新加载。确保在主UI线程上完成此操作。使用
BeginInvoke();
是异步的,我经历过需要大约30秒才完成的时间。