2

I want to show a 'please wait' message box while my main form is doing a lengthy task. As for my case, the lengthy task is transmitting serial protocol. Below is my code:

public void transmitprotocol()
{    
    try
    {
         MessageBox.Show("Please wait. Uploading logo.", "Status");

         // Transmitting protocol coding here. Takes around 2 minutes to finish.

    }
    catch (Exception ex)
    {
        Debug.WriteLine(ex.ToString());
    }
}

I've tried the above method using MessageBox like the above coding, but I always have to close the MessageBox only it will start transmitting protocol. Is there any method I can do to still show the 'please wait' MessageBox while it transmit protocol?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Coolguy
  • 2,225
  • 12
  • 54
  • 81

3 Answers3

9

You will need to do the expensive operation on a background thread. For that, use either a BackgroundWorker or the new Parallelization Library (.NET 4 and so on).

Actually you need to close the dialog because it blocks the execution until you, well, close it. What you do is that you start the operation, then show the dialog and then, once the operation is done, you close the dialog.

Now, if you're using WPF I will strongly suggest you to don't use a Dialog Box and instead use a Busy Indicator, it's free, pretty easy to use and not so ugly as the Message Box.

EDIT: Now that you specify you're using WinForms, then go ahead, implement the background worked and, why not, a transparent window without chrome whose purpose is to show a Busy label. Once the background worker ends you close that window.

enter image description here

Erre Efe
  • 15,387
  • 10
  • 45
  • 77
  • 1
    Paralellisation is available from .NET 4.0 on. – Tim Sep 20 '12 at 03:43
  • You're welcome. Good answer by the way - I just wanted to make sure OP (or anyone else reading) knew they could use the Parallel stuff from 4.0 on :) – Tim Sep 20 '12 at 03:47
  • Thanks for the idea Randolf R-F. But do you have any sample coding on BackgroundWorker application which is similar to my case? – Coolguy Sep 20 '12 at 03:56
  • @Coolguy Follow the link under BackgroundThread, there you'll find the official documentation with a full example including cancellation support for the background thread. – Erre Efe Sep 20 '12 at 03:59
6

You have to prepare a backgroundworker and use a windows form instead of MessageBox. Something like this as simple as copy/paste:

    Form1 msgForm;
    public void transmitprotocol()
    {
        BackgroundWorker bw = new BackgroundWorker();
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
        //you can use progresschange in order change waiting message while background working
        msgForm = new Form1();//set lable and your waiting text in this form
        try
        {
            bw.RunWorkerAsync();//this will run all Transmitting protocol coding at background thread

            //MessageBox.Show("Please wait. Uploading logo.", "Status");
            msgForm.ShowDialog();//use controlable form instead of poor MessageBox
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.ToString());
        }
    }

    void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        // Transmitting protocol coding here. Takes around 2 minutes to finish. 
        //you have to write down your Transmitting codes here
        ...

        //The following code is just for loading time simulation and you can remove it later. 
        System.Threading.Thread.Sleep(5*1000); //this code take 5 seconds to be passed
    }
    void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        //all background work has complete and we are going to close the waiting message
        msgForm.Close();
    }
Hamid
  • 817
  • 1
  • 13
  • 29
  • I've tried your coding Hamid, but there's some problem with the form part. My Form1 is already the main winform with buttons on it. What I want to do is, when I click a button, only then it will begin transmit protocols. So, is 'Form1 msgForm;' correct? – Coolguy Sep 20 '12 at 05:58
  • Create new Windows Form and set label it in ( and if you need a cancel button) then use it instead of Form1. This new Form will uses like a MessageBox form – Hamid Sep 20 '12 at 06:14
  • Thanks Hamid. I've created a Form2 for the 'please wait' message. But there's another problem here. When I click the button for transmit protocol, it won't run. It show the 'please wait' message for a second only then close by itself. No protocol had been transmitted. What's wrong? – Coolguy Sep 20 '12 at 06:18
  • Write down your checking codes in the void bw_DoWork(object sender, DoWorkEventArgs e) – Hamid Sep 20 '12 at 06:32
  • I've tried and seems like if you put try{}catch{} statement in void bw_DoWork, it can't run. It only will run after I take out the try{}catch{} statement. – Coolguy Sep 20 '12 at 06:45
  • But how come each time I click, it will transmit the protocols more times than previously. For example, like the first time I click the button, it transmit protocol once. Then I click the button second time, it transmit the protocol twice. Then I click third time, it transmit the same protocol 3 times... and so on... Why is it like this? – Coolguy Sep 20 '12 at 06:48
  • You can disable the button or check some conditions before background wunning code in your transmitprotocol() . Actually your question was about 'Please wait' message, so create new question for your next issue. Thanks – Hamid Sep 20 '12 at 06:53
  • Hamid, but aren't that it will only do once the coding in void bw_DoWork? Why is it keep increasing the number of protocol transmit every time I click the button? – Coolguy Sep 20 '12 at 06:58
  • @Coolguy, Use Breakpoint in your code (also in he catch block) and if you didn't find a solution then post another question with your transmit codes in it. I am sure that you need some sort of conditions and list clearing in your code. – Hamid Sep 20 '12 at 07:10
0

The easiest way to do this is to open the splash with show() Open the desired form and pass it an instance of the splash form in the constructor:

        Wait myWaitDialog = new Wait(); //Wait is your splash
        myWaitDialog.Show();
        myWaitDialog.Refresh(); //Otherwise screen fails to refresh splash
        ScheduleClassForm myForm = new ScheduleClassForm(myWaitDialog);
        myForm.TopLevel = true;
        myForm.ShowDialog();

Add this code to your resulting form constructor:

    public ScheduleClassForm(Form WaitWindow)
    {            
       InitializeComponent();
       WaitWindow.Close();
    }

For me it failed in the form_load but worked in the constructor. Make sure your work is done (e.g. db load) prior to closing the WaitWindow.

  • I've added a well tested and simple solution here: https://stackoverflow.com/questions/15769276/best-way-to-display-a-progress-form-while-a-method-is-executing-code/45406217#45406217 – user2288580 Jul 31 '17 at 01:11