How do I show a “Loading . . . please wait” message in Winforms for a long loading form?

StackOverflow https://stackoverflow.com/questions/9072956

  •  20-04-2021
  •  | 
  •  

Pregunta

I have a form that is very slow because there are many controls placed on the form.

As a result the form takes a long time to loaded.

How do I load the form first, then display it and while loading delay show another form which that have message like "Loading... please wait.?"

¿Fue útil?

Solución

Using a separate thread to display a simple please wait message is overkill especially if you don't have much experience with threading.

A much simpler approach is to create a "Please wait" form and display it as a mode-less window just before the slow loading form. Once the main form has finished loading, hide the please wait form.

In this way you are using just the one main UI thread to firstly display the please wait form and then load your main form.

The only limitation to this approach is that your please wait form cannot be animated (such as a animated GIF) because the thread is busy loading your main form.

PleaseWaitForm pleaseWait=new PleaseWaitForm ();

// Display form modelessly
pleaseWait.Show();

//  ALlow main UI thread to properly display please wait form.
Application.DoEvents();

// Show or load the main form.
mainForm.ShowDialog();

Otros consejos

I looked at most the solutions posted, but came across a different one that I prefer. It's simple, doesn't use threads, and works for what I want it to.

http://weblogs.asp.net/kennykerr/archive/2004/11/26/where-is-form-s-loaded-event.aspx

I added to the solution in the article and moved the code into a base class that all my forms inherit from. Now I just call one function: ShowWaitForm() during the frm_load() event of any form that needs a wait dialogue box while the form is loading. Here's the code:

public class MyFormBase : System.Windows.Forms.Form
{
    private MyWaitForm _waitForm;

    protected void ShowWaitForm(string message)
    {
        // don't display more than one wait form at a time
        if (_waitForm != null && !_waitForm.IsDisposed) 
        {
            return;
        }

        _waitForm = new MyWaitForm();
        _waitForm.SetMessage(message); // "Loading data. Please wait..."
        _waitForm.TopMost = true;
        _waitForm.StartPosition = FormStartPosition.CenterScreen;
        _waitForm.Show();
        _waitForm.Refresh();

        // force the wait window to display for at least 700ms so it doesn't just flash on the screen
        System.Threading.Thread.Sleep(700);         
        Application.Idle += OnLoaded;
    }

    private void OnLoaded(object sender, EventArgs e)
    {
        Application.Idle -= OnLoaded;
        _waitForm.Close();
    }
}

MyWaitForm is the name of a form you create to look like a wait dialogue. I added a SetMessage() function to customize the text on the wait form.

You want to look into 'Splash' Screens.

Display another 'Splash' form and wait until the processing is done.

Here is an example on how to do it.

Another way of making "Loading screen" only display at certain time is, put it before the event and dismiss it after event finished doing it's job.

For example: you want to display a loading form for an event of saving result as MS Excel file and dismiss it after finished processing, do as follows:

LoadingWindow loadingWindow = new LoadingWindow();

try
{
    loadingWindow.Show();                
    this.exportToExcelfile();
    loadingWindow.Close();
}
catch (Exception ex)
{
    MessageBox.Show("Exception EXPORT: " + ex.Message);
}

Or you can put loadingWindow.Close() inside finally block.

A simple solution:

using (Form2 f2 = new Form2())
{
    f2.Show();
    f2.Update();

    System.Threading.Thread.Sleep(2500);
} // f2 is closed and disposed here

And then substitute your Loading for the Sleep.
This blocks the UI thread, on purpose.

You should create a background thread to to create and populate the form. This will allow your foreground thread to show the loading message.

You can take a look at my splash screen implementation: C# winforms startup (Splash) form not hiding

I put some animated gif in a form called FormWait and then I called it as:

// show the form
new Thread(() => new FormWait().ShowDialog()).Start();

// do the heavy stuff here

// get the form reference back and close it
FormWait f = new FormWait();
f = (FormWait)Application.OpenForms["FormWait"];
f.Close();

Well i do it some thing like this.

        NormalWaitDialog/*your wait form*/ _frmWaitDialog = null;


        //Btn Load Click Event
        _frmWaitDialog = new NormalWaitDialog();
        _frmWaitDialog.Shown += async (s, ee) =>
        {
            await Task.Run(() =>
           {
               // DO YOUR STUFF HERE 

               //Made long running loop to imitate lengthy process
               int x = 0;
               for (int i = 0; i < int.MaxValue; i++)
               {
                   x += i;
               }

           }).ConfigureAwait(true);
            _frmWaitDialog.Close();
        };
        _frmWaitDialog.ShowDialog(this);

The best approach when you also have an animated image is this one:

1- You have to create a "WaitForm" that receives the method that it will executed in background. Like this one

public partial class WaitForm : Form
{
    private readonly MethodInvoker method;

    public WaitForm(MethodInvoker action)
    {
        InitializeComponent();
        method = action;
    }

    private void WaitForm_Load(object sender, EventArgs e)
    {
        new Thread(() =>
        {
            method.Invoke();
            InvokeAction(this, Dispose);
        }).Start();
    }

    public static void InvokeAction(Control control, MethodInvoker action)
    {
        if (control.InvokeRequired)
        {
            control.BeginInvoke(action);
        }
        else
        {
            action();
        }
    }
}

2 - You can use the Waitform like this

private void btnShowWait_Click(object sender, EventArgs e)
{
    new WaitForm(() => /*Simulate long task*/ Thread.Sleep(2000)).ShowDialog();
}

or if you don't want anything fancy like animation etc. you can create a label and dock it to form then change it's z-index from document outline window to 0 and give it a background color so other controls wont be visible than run Application.DoEvents() once in form load event and do all your coding in form shown event and at the and of shown event set your label visible property to false then run Application.DoEvents() again.

I know it is wery late, but I fonded this project and I would like to share with you, it is very usefull and sample Simple Display Dialog of Waiting in WinForms

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top