Winform更新长时间运行的任务

当应用程序执行长时间运行的任务时,您是否有一个很好的解决方案来保持“请等待”winform“绘制”?

我已经尝试在每一步使用form.refresh(),但是有一些长时间运行的查询,这意味着这不够频繁。

基本上这个SO问题但是,通过VSTO(而不是Python)在Excel中的C#。

这是 C#代码的一个很好的例子 。

它专门用于启动画面,但它创建一个请等待窗口几乎是相同的过程(可能减去一些华丽的不透明度)。

关键信息是您需要一个单独的线程。 这可能会使事情变得复杂,但文章提供了如何正确执行此操作的良好覆盖/示例。

正如statichippo所提到的,我会使用BackgroundWorker类。 其目的是简化multithreading并允许工作线程在不锁定GUI的情况下进行耗时的处理。

以下是MSDN的引用:

BackgroundWorker类允许您在单独的专用线程上运行操作。 下载和数据库事务等耗时的操作可能会导致用户界面(UI)在运行时停止响应。 当您需要响应式UI并且遇到与此类操作相关的长时间延迟时,BackgroundWorker类提供了一种方便的解决方案。

这是一个很好的教程如何在Windows窗体中使用BackgroundWorker类: 使用BackgroundWorker类在WinForms中实现multithreading

对于复杂场景,在C#中实现multithreading有更复杂的方法,但对于大多数简单场景,BackgroundWorker工作得很好(至少对我来说)。

以下是我在C#Multi Threading上从谷歌中提取的一些链接:
MSDN线程
C#中multithreading简介

另一种选择是使用异步委托在线程池线程上显示表单。

建议将线程池中的线程用于在整个应用程序持续时间内不会持续的较短生存线程。 由于这是显示一个短命的请等待窗口,所以线程池是一个合理的选择。

Action委托(.NET 2.0+)与它的BeginInvoke()方法一起使用,以在线程池线程上自动运行委托代码。

一些说明:

  • 对任何跨线程GUI调用使用Control.BeginInvoke非常重要,例如在ClosePleaseWait()中关闭请等待表单。
  • 另外, m_pleaseWaitForm.ShowDialog(); 实际上在新线程中启动一个新的消息循环。 这就是让等待表格保持活力的原因。
  • 由于使用了线程池线程,因此该线程自动成为后台线程,并在主应用程序关闭时终止。
  • 除了在另一个线程上运行外,Form2没有什么特别之处。 您可以在其上放置任何子控件,如Picturebox,标签等。
  • (MethodInvoker)delegate { ... }只是一种在委托内联中运行代码的.NET 2.0方式。

下面的示例可以添加到包含Form1的WinForms项目:主窗体和Form2:请等待表单。

  private Form2 m_pleaseWaitForm = null; private void Form1_Shown(object sender, EventArgs e) { // This code could also be placed in eg. a button click event handler. Action a = new Action(ShowPleaseWait); a.BeginInvoke(this.Bounds, null, null); // Do your long running tasks ClosePleaseWait(); } private void ShowPleaseWait(Rectangle bounds) { // This method runs on the new thread. m_pleaseWaitForm = new Form2(); m_pleaseWaitForm.TopMost = true; m_pleaseWaitForm.Location = new Point(bounds.Left + bounds.Width / 2 - m_pleaseWaitForm.Width / 2, bounds.Top + bounds.Height / 2 - m_pleaseWaitForm.Height / 2); m_pleaseWaitForm.ShowDialog(); } private void ClosePleaseWait() { m_pleaseWaitForm.BeginInvoke((MethodInvoker)delegate { m_pleaseWaitForm.Close(); }); } 

使用BackgroundWorker