Winform 更新长时间运行的任务

发布于 2024-08-18 18:11:26 字数 278 浏览 4 评论 0原文

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

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

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

Do you have a good solution for keeping a 'Please wait' winform 'painted' while an application is performing a long running task ?

I've tried using form.refresh() on each step, but there are a few long running queries that take place, which means that this isn't frequent enough.

Basically this SO Question but, on C# in Excel through VSTO (rather than Python).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

许你一世情深 2024-08-25 18:11:26

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

以下是 MSDN 的引用:

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

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

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

以下是我从 Google 获取的有关 C# 多线程的一些链接:
MSDN 线程
C# 中的多线程简介

As statichippo mentioned, I would use the BackgroundWorker Class. Its purpose is to simplify multi-threading and allow for a worker thread to do the time consuming processing without locking the GUI.

Here is a quote from MSDN:

The BackgroundWorker class allows you
to run an operation on a separate,
dedicated thread. Time-consuming
operations like downloads and database
transactions can cause your user
interface (UI) to seem as though it
has stopped responding while they are
running. When you want a responsive UI
and you are faced with long delays
associated with such operations, the
BackgroundWorker class provides a
convenient solution.

Here is a good tutorial how to use the BackgroundWorker class in windows forms: Implementing multi-threading in WinForms using the BackgroundWorker class

There are more complicated ways to implement Multi-Threading in C# for complex scenarios but for most simple scenarios the BackgroundWorker works great (for me at least).

Here are some links I pulled from Google on C# Multi Threading:
MSDN Threading
Introduction to Multithreading in C#

傲性难收 2024-08-25 18:11:26

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

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

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

一些注意事项:

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

下面的示例可以添加到包含 Form1:主窗体和 Form2:请稍候窗体的 WinForms 项目中。

   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(); });
    }

Another option is to use an asynchronous delegate to show the form on a threadpool thread.

Threads in the threadpool are recommended for shorter lived threads that do not last for the entire application duration. As this is to display a short-lived please wait window, the threadpool is a reasonable choice.

The Action delegate (.NET 2.0+) is used along with it's BeginInvoke() method to automatically run the delegate code on a threadpool thread.

Some notes:

  • It is important to use Control.BeginInvoke for any cross thread GUI calls, such as closing the please wait form in ClosePleaseWait().
  • Also, the m_pleaseWaitForm.ShowDialog(); actually starts a new message loop in the new thread. This is what keeps the please wait form alive.
  • Because a threadpool thread is used, this thread is automatically a background thread and will be terminated if the main application is closed.
  • Apart from running on another thread, there is nothing special about Form2. You can place any child controls such as Pictureboxes, labels etc on it.
  • (MethodInvoker)delegate { ... } is just a .NET 2.0 way of running code in a delegate inline.

The example below can be added to a WinForms project containing Form1: the main form, and Form2: the please wait form.

   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(); });
    }
Spring初心 2024-08-25 18:11:26

这是一个很好的示例,其中包含 C# 代码。

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

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

Here's a good example with code in C#.

It is for splash screens specifically, however it is almost identical process (perhaps minus some of the flashy Opacity) to create a Please wait window.

The key information is that you will need a separate thread. This can complicate things however the article gives a good coverage/example of how to do it correctly.

药祭#氼 2024-08-25 18:11:26

使用后台工作者

Use a BackgroundWorker

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文