从单独类中的另一个线程更新 UI
您遇到从运行单独类的线程更新 WPF UI 的常见问题。 UI 在冗长的计算过程中冻结,您需要通知用户进度。
使用线程和事件的解决方案
示例代码:
class MainWindow : Window { private void startCalc() { // Prepare input inputValues input = ...; // Create calculation class and register to its event CalcClass calc = new CalcClass(); calc.ProgressUpdate += (s, e) => Dispatcher.Invoke(() => { /* UI Update */ }); // Start calculation in a separate thread Thread calcthread = new Thread(new ParameterizedThreadStart(calc.testMethod)); calcthread.Start(input); } } class CalcClass { public event EventHandler ProgressUpdate; public void testMethod(object input) { // Raise event to trigger UI update if (ProgressUpdate != null) ProgressUpdate(this, new YourEventArgs(status)); // Notify UI with status updates } }
.NET 4.5 及更高版本的替代方案
考虑以下使用较新的替代方案功能:
使用任务:用任务替换线程以简化线程管理。
使用异步/等待:推迟计算直到它需要通过将 UI 更新方法标记为异步来实现。
强烈使用类型化通用事件: 使用强类型通用事件将自定义数据类型传递给事件。
带有扩展的改进示例:
class MainWindow : Window { Task calcTask = null; // Stores task for later checking void StartCalc() { var calc = PrepareCalc(); calcTask = Task.Run(() => calc.TestMethod(input)); // Start in background } async Task CalcAsync() { var calc = PrepareCalc(); await Task.Run(() => calc.TestMethod(input)); // Await completion } CalcClass PrepareCalc() { // Prepare input and create calc object var calc = new CalcClass(); calc.ProgressUpdate += (s, e) => Dispatcher.Invoke(() => { /* UI Update */ }); return calc; } } class CalcClass { public event EventHandler<EventArgs<YourStatus>> ProgressUpdate; public TestMethod(InputValues input) { // Raise event to trigger UI update ProgressUpdate?.Raise(this, new EventArgs<YourStatus>(status)); // Raise with status } }
其他注意:
以上是如何从不同类中的单独线程安全地更新 WPF UI?的详细内容。更多信息请关注PHP中文网其他相关文章!