开发者

Winform updates on long running tasks

开发者 https://www.devze.com 2022-12-16 17:50 出处:网络
Do you have a good solution for keeping a \'Please wait\' wi开发者_StackOverflow社区nform \'painted\' while an application is performing a long running task ?

Do you have a good solution for keeping a 'Please wait' wi开发者_StackOverflow社区nform '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).


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#


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


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.


Use a BackgroundWorker

0

精彩评论

暂无评论...
验证码 换一张
取 消