【问题标题】:Winform updates on long running tasksWinform 更新长时间运行的任务
【发布时间】:2010-01-19 14:51:50
【问题描述】:

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

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

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

【问题讨论】:

  • 这真的是 web-forms,还是 winforms?您在谈论 Excel 和 VSTO。如果是网络表单,则没有刷新方法。
  • 抱歉,是的,Winforms,而不是 Webforms.. 已经编辑了问题......这已经是漫长的一天......
  • 有完整源代码示例的最终解决方案吗?使用 C#、SignalR 的步骤使用长时间运行的进程怎么样?

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


【解决方案1】:

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

这是来自MSDN的引用:

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

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

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

以下是我从 Google 获取的关于 C# 多线程的一些链接:
MSDN Threading
Introduction to Multithreading in C#

【讨论】:

    【解决方案2】:

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

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

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

    一些注意事项:

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

    下面的例子可以添加到一个 WinForms 项目中,其中包含 Form1:主窗体和 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(); });
        }
    

    【讨论】:

      【解决方案3】:

      Here's a good example 使用 C# 代码。

      它专门用于启动屏幕,但创建“请稍候”窗口的过程几乎相同(可能减去了一些华丽的不透明度)。

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

      【讨论】:

      • 感谢您提供此链接。效果非常好,并且非常好地集成到我的 Excel VSTO 应用程序中!
      【解决方案4】:

      使用 BackgroundWorker

      【讨论】:

      • 我累了——我以为这是winforms。答案应该是使用 AJAX(MS AJAX 可以正常工作)。您可以使用 Timer 控件来检查状态。然后你可以在完成时重定向。
      • 抱歉投反对票,问题已从 webforms=>winforms 更改。
      • 我相信 statichippo 是正确的。使用 backgroundworker 线程应该会为您执行此操作。
      猜你喜欢
      • 1970-01-01
      • 2014-03-13
      • 2016-03-07
      • 2012-08-13
      • 2022-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多