Winform更新长时间运行的任务

时间:2010-01-19 14:51:51

标签: c# winforms vsto long-running-processes

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

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

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

4 个答案:

答案 0 :(得分:3)

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

以下是MSDN的引用:

  

BackgroundWorker类允许您   在一个单独的,   专用线程。耗时的   下载和数据库等操作   交易可能会导致您的用户   界面(UI)看起来好像它   他们已经停止了回应   运行。当您需要响应式UI时   你面临着长时间的拖延   与此类操作相关联的   BackgroundWorker类提供了一个   方便的解决方案。

这是一个很好的教程,如何在Windows窗体中使用BackgroundWorker类:​​Implementing multi-threading in WinForms using the BackgroundWorker class

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

以下是我在C#Multi Threading上从Google上提取的一些链接:
MSDN Threading
Introduction to Multithreading in C#

答案 1 :(得分:1)

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

对于在整个应用程序持续时间内不能持续的较短生存线程,建议使用线程池中的线程。由于这是显示一个短暂的请等待窗口,因此线程池是一个合理的选择。

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<Rectangle> a = new Action<Rectangle>(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(); });
    }

答案 2 :(得分:0)

使用BackgroundWorker

答案 3 :(得分:0)

带有C#代码的

Here's a good example

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

关键信息是您需要一个单独的线程。这可能会使事情变得复杂,但文章提供了一个很好的覆盖/示例,说明如何正确地做到这一点。