views:

49

answers:

2

Hi,

I'm using .net 2.0 and I've created a form (System.Windows.Forms.Form) for displaying information during long running tasks.

When I start a long running task, I create a new instance of this form, call .Show() and start the BackgroundWorker. But even though I use a BackgroundWorker for doing the work, the form indeed shows up, but immediatly blocks and doesn't response until the background worker has finished, i.d. the form appears but the content (a gif and a textbox) isn't shown?

The strange thing is, this doesn't happen when the job for the BackgroundWorker is that intensive!?! How come?

Example:

private void UpdateReportingTab()
{
    //p is an instance variable; Progressbar is just a simple form control
    //showing the passed message
    p = new Progressbar("Loading Data...");
    p.Show();
    BackgroundWorker bw = new BackgroundWorker();
    bw.WorkerSupportsCancellation = true;
    bw.DoWork += new DoWorkEventHandler(bw_DoWork);
    bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
    bw.RunWorkerAsync();
}

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{            
    p.BeginInvoke(new MethodInvoker(p.Close));
}

private void bw_DoWork(object sender, DoWorkEventArgs e)
{
    if (this.InvokeRequired)
    {
        this.BeginInvoke(new MethodInvoker(delegate()
        {
            //long running database queries, whose results update text fields
            //while text fields are filled p show "no response"
            TextEditItems.Text = Convert.ToString(itemsDao.getItemCount());
            ....
        }
    }
}

Thanks!

Andi

+3  A: 

Because you do not effectively run a background worker, dude ;)

The background worker INVOKES INTO THE MAIN THREAD - which puts the work back into the main UI thread where.

You should NOT INVOKE BACK UNTL YOU NEED To.

Particularly:

  • Make the long running database query, retrieve the results
  • THEN invoke back into the UI thread to update the TextEditItems

The moment you invoke back you are back on the UI THREAD - in your case the background worker therad does only the invoke back... which makes the background worker senseless.

TomTom
Whoa, steady on the caps there...
cofiem
Thanks, you're right. How could I've missed this :)?
Andreas
+2  A: 

By using BeginInvoke, you're actually executing the code on the UI thread. Your BackgroundWorker is useless here, the bw_DoWork will return immediately and the UI will be frozen.

If you need some data from the controls, retrieve it before you start the BackgroundWorker, and do the work on the BGW thread rather than calling Invoke or BeginInvoke

Thomas Levesque