Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to display a progress form while a method is executing code?

I have a WinForm load method that takes a long time to gather some data to display to the user.

I display a form with a large font with the word "Loading" while this method is executing.

However sometimes this error comes up and the "Loading" progress form does not close and then eventually my whole application will just exit:

Error creating window handle. at System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp)

Is there a better way to display my progress/loading form while I am executing code in the load method?

This is my code:

//I launch a thread here so that way the Progress_form will display to the user
//while the Load method is still executing code.  I can not use .ShowDialog here
//or it will block.

//Progress_form displays the "Loading" form    
Thread t = new Thread(new ThreadStart(Progress_form));  

t.SetApartmentState(System.Threading.ApartmentState.STA);
t.IsBackground = true;
t.Start();

//This is where all the code is that gets the data from the database.  This could
//take upwards of 20+ seconds.

//Now I want to close the form because I am at the end of the Load Method                         

try
{
   //abort the Progress_form thread (close the form)
   t.Abort();
   //t.Interrupt();
}
catch (Exception)
{
}
like image 716
fraXis Avatar asked Dec 15 '22 12:12

fraXis


2 Answers

A BackgroundWorker is a great way to perform a long running operation without locking the UI thread.

Use the following code to start a BackgroundWorker and display a loading form.

// Configure a BackgroundWorker to perform your long running operation.
BackgroundWorker bg = new BackgroundWorker()
bg.DoWork += new DoWorkEventHandler(bg_DoWork);
bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);

// Start the worker.
bg.RunWorkerAsync();

// Display the loading form.
loadingForm = new loadingForm();
loadingForm.ShowDialog();

This will cause the following method to be executed on a background thread. Note that you cannot manipulate the UI from this thread. Attempting to do so will result in an exception.

private void bg_DoWork(object sender, DoWorkEventArgs e)
{
    // Perform your long running operation here.
    // If you need to pass results on to the next
    // stage you can do so by assigning a value
    // to e.Result.
}

When the long running operation completes, this method will be called on the UI thread. You can now safely update any UI controls. In your example, you would want to close the loading form.

private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // Retrieve the result pass from bg_DoWork() if any.
    // Note, you may need to cast it to the desired data type.
    object result = e.Result;

    // Close the loading form.
    loadingForm.Close();

    // Update any other UI controls that may need to be updated.
}
like image 57
Timothy Schoonover Avatar answered Mar 30 '23 00:03

Timothy Schoonover


Ive successfully tested this on .NET 4.0. (WinForms) I'm reasonably certain that this will work on .NET 4.0+ and should be a useful code snippet to reuse in most of your projects that require closing forms at the end of a process.

private void SomeFormObject_Click(object sender, EventArgs e)
{
    myWait = new YourProgressForm();//YourProgressForm is a WinForm Object
    myProcess = new Thread(doStuffOnThread);
    myProcess.Start();
    myWait.ShowDialog(this);
}

private void doStuffOnThread()
{
    try
    {
        //....
        //What ever process you want to do here ....
        //....

        if (myWait.InvokeRequired) {
            myWait.BeginInvoke( (MethodInvoker) delegate() { closeWaitForm(); }  );
        }
        else
        {
            myWait.Close();//Fault tolerance this code should never be executed
        }
    }
    catch(Exception ex) {
        string exc = ex.Message;//Fault tolerance this code should never be executed
    }
}

private void closeWaitForm() {
    myWait.Close();
    MessageBox.Show("Your Process Is Complete");
}
like image 33
user2288580 Avatar answered Mar 30 '23 01:03

user2288580