4

In a legacy app we have a single winform that locks up while executing code on a button click...well it doesn't lock up it just "stops responding" until the code executes.

What is the best (least amount of code and working) way to wrap the code below into a separate thread and show a loading window (frmLoading) while it executes? I know this should be relatively simple, but I have tried a few different things that haven't quite worked out.

private void btnSynch_Click(object sender, EventArgs e)
{
    btnSynch.Enabled = false;

    if(chkDBSynch.Checked)
        PerformDBSyncronization();

    if(chkAppSynch.Checked)
        PerformApplicationSyncronization();

    btnSynch.Enabled = true;
}

EDIT: Ok, I should have mentioned have tried backgroundworker, but I figured out where I was tripping up....This code would execute and the loading form was getting thrown behind the main form which is why I thought it wasn't working. Can Anyone tell me how to prevent this from happening?

  private void btnSynch_Click(object sender, EventArgs e)
    {

        btnSynch.Enabled = false;
        frmLoading loadingWindow = new frmLoading();
        loadingWindow.Show();

        BackgroundWorker bw = new BackgroundWorker();
        bw.DoWork += (s, args) =>
        {

            Thread.Sleep(6000); //TODO:just for testing 
            if(chkDBSynch.Checked)
            PerformDBSyncronization();

            if(chkAppSynch.Checked)
            PerformApplicationSyncronization();
        };
        bw.RunWorkerCompleted += (s, args) =>
        {
            loadingWindow.Close();
        };
        bw.RunWorkerAsync();

        btnSynch.Enabled = true;
    }
AGoodDisplayName
  • 5,543
  • 7
  • 35
  • 50

2 Answers2

2

I feel silly...The loading form was popping up behind the the main form which is why I thought it wasn't opening. I set the TopMost property to true and everything works as expected.

Edit:
Here is a good explanation why my form was popping up behind my window, I just wasn't expecting the thread that was opening the window to not use the main form as the owner.

Why use a owner window in MessageBox.Show?

I ended up with my code looking like

        frmLoading loadingWindow = new frmLoading();
        loadingWindow.Show(this);

        BackgroundWorker bw = new BackgroundWorker();
        bw.DoWork += (s, args) =>
        {
            this.Invoke(new MethodInvoker(() => this.Enabled = false));

            if(chkDBSynch.Checked)
            PerformDBSyncronization();

            if(chkAppSynch.Checked)
            PerformApplicationSyncronization();
        };
        bw.RunWorkerCompleted += (s, args) =>
        {
            loadingWindow.Close();
            this.Invoke(new MethodInvoker(() => this.Enabled = true));

        };

        bw.RunWorkerAsync();
Community
  • 1
  • 1
AGoodDisplayName
  • 5,543
  • 7
  • 35
  • 50
  • 1
    Set the loading form's owner to be the main form instead: `loadingForm.ShowDialog(this)`. – Tergiver Apr 15 '11 at 22:04
  • @Tergiver - Thanks, this is actually what I ended up doing, but I didn't use ShowDialog becuase the the main form would wait for the result. (I just set the topmost property as a quick test)...I'll update my answer. – AGoodDisplayName Apr 18 '11 at 15:55
  • Using ShowDialog prevents the user from interacting with the owner window, it does not "wait for the result". The UI thread will still be pumping messages, the owner window will still be "alive". If you use Show, the user can interact with your main window, causing the loading form to disappear, and activating controls that are probably not ready to be activated. – Tergiver Apr 18 '11 at 20:37
  • @Tergiver - I hear you and thats certainly how I thought it worked, but thats not what was happening when I tried to use showdialog...breakpoints on the main form were never getting hit... maybe because of the way I implemented the multi-threading and the point at which I was calling ShowDialog? – AGoodDisplayName Apr 18 '11 at 21:10
  • It looks like you are disabling the main window and using `Show` which is effectively the same thing as `ShowDialog`. If you want to figure out why you couldn't use ShowDialog, whip up a simple demonstration and post it as a new question. – Tergiver Apr 19 '11 at 14:49
0

Use a BackgroundWorker for this purpose.

jonsca
  • 10,218
  • 26
  • 54
  • 62
  • I've tried backgroundworker, but I am doing something wrong. The loading form never pops up....I was kinda hoping some one had some code examples. – AGoodDisplayName Apr 15 '11 at 20:51
  • [This](http://www.dotnetperls.com/backgroundworker) is a very friendly introduction. If you have access to the book [C# 2008 Express Edition: Build a program now](http://www.microsoft.com/learning/en/us/book.aspx?ID=12281&locale=en-us) it has a good example in it. – jonsca Apr 15 '11 at 21:07