Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Make Sure UI is Responsive Using BackgroundWorker

Is BackgroundWorker in c# Thread Safe?

The reason I ask this is because I get a

Controls created on one thread cannot be parented to a control on a different thread

exception with it. This is my DoWork event code:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{



    var openFile = document.Open(MyFileName);
    e.Result = openFile;
}

where document is an UI control that is initialized when the parent form is created. During Open method various properties in document will be filled.

I tried to change the code to invoke, yet the same problem persists. i.e,

document.GetType().GetMethod("Open)".Invoke(document, new object[]{MyFileName})

will yield the same error as the above.

Any idea how to manipulate the document control? In other words, how to make the above code work?

Edit: It was suggested that I use Control.Invoke, but it still didn't work ( both of the threads hanged). This is the code I tried:

private delegate bool OpenFile(string filePath);
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{



    OpenFile oF = new OpenFile(document.Open);
    var openFile = Invoke(oF, MyFileName);  // it doesn't really matter whether I use BeginInvoke or Invoke, or other Control.Invoke, the end result is the same. Both the main thread hosting the document and the thread that launches the UI hanged.

    e.Result = openFile;
}
like image 939
Graviton Avatar asked Jan 18 '10 09:01

Graviton


2 Answers

It isn't the thread that's the problem it's the fact that it's trying to call a method on a UI control. In both WPF and WinForms controls can only be called on the UI thread (of which there is typically one). You don't say which you are using but you need to call the Control.Invoke method for WinForms or Dispatcher.Invoke for WPF.

The Invoke() reflection method you show will actually invoke the method on the current thread.

like image 89
GraemeF Avatar answered Sep 23 '22 14:09

GraemeF


You can either invoke as Mehrdad Afshari suggested, or you can make use of the bgw's progress event which comes back on the UI thread. Or the work completed event which also comes back on the UI thread. The difference between the two is WorkCompleted is fired only once at the end. Progress is fired by you from DoWork.

like image 20
Noel Kennedy Avatar answered Sep 25 '22 14:09

Noel Kennedy