How to Make Sure UI is Responsive Using BackgroundWorker?

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.

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.

I tried this piece of code in my DoWork event, and it still doesn't work: this. Invoke(document. Open) – Graviton Jan 18 '10 at 13:31 You're still calling the wrong method.

If document is a Windows Forms control then you would call document. Invoke(MyMethod) where MyMethod is a delegate that calls document.Open. Depending on the signature you may be able to call document.

Invoke(document. Open) directly. – GraemeF Jan 18 '10 at 13:41 @GraemeF, what if document.

Invoke not available? – Graviton Jan 18 '10 at 13:42 Then it's not a control. Can you just tell us what document is?

– GraemeF Jan 18 '10 at 13:43 It's just a normal class from third party library, sorry for the confusion – Graviton Jan 18 '10 at 13:44.

While it's unclear to me what you exactly mean by thread-safety of a BackgroundWorker, the problem is not that object; Windows Forms controls are designed to be manipulated on a single thread (the UI thread). You should not manipulate Windows Forms objects on different threads. You can invoke actions in the UI thread from other threads by using the Control.

Invoke method (the Invoke method you are currently using is provided by reflection and is totally unrelated to this problem): Invoke(new Action(MethodToRunInUIThread)); void MethodToRunInUIThread() { // do stuff here. } By the way, it doesn't make sense to use a background worker if all you are doing is manipulating UI objects.

Mehdrad, I need a backgroundworker to keep the UI responsive, which is why it makes sense. – Graviton Jan 18 '10 at 10:03 @Ngu Soon Hui: Of course, if you have a long running task that's not just UI operations, you'll use that. If all you're doing in the DoWork method is to manipulate UI objects, you shouldn't use the BackgroundWorker and the reason is you'll ultimately have to do all those UI operations on the UI thread.

– Mehrdad Afshari Jan 18 '10 at 10:10 It can make sense and it might be more subtle. The thread might just notify the "UI thread" that "something new happened", and then it's up to whatever notification handler the UI has to update the UI if needed. – Johann Gerell Jan 18 '10 at 10:12 @Johann: I know.In that case if all you're doing is UI operations will be false, you know.

I'm saying this because apparently the code that OP posted is simply calling a method on a control which should be done using Invoke and Invoke simply runs the method on the UI thread, so it's pointless to use a BackgroundWorker here. – Mehrdad Afshari Jan 18 '10 at 10:15.

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.

– Graviton Jan 18 '10 at 10:11 2 perhaps this is a missunderstanding of what BGW does for you. If you are doing a lot of manipulation of UI controls and this is therefore slow, and causes your UI to pull a whitey or appear to freeze, bgw can't help you! However, if you are doing something else (other than touching ui controls), for example going to a slow webservice or the DB, then doing this on the bgw will allow your ui to remain responsive.

For example, you can do intensive operation x, then use the progress event to report back to your UI to say operation x completed, here are the interim results, doing operation y next – Noel Kennedy Jan 18 '10 at 10:20.

If that functionality of the UI Control takes that long to execute, there may not be much you can do. "Freezing" occurs when a long-running operation happens on the UI thread, and if that function of the control was not specifically made thread-safe, it must be run on the main thread. Normally, you'd want to separate the "document" functionality away from the control that displays it.

This way, your document could be loaded on a separate, independent thread and be displayed later when ready. Otherwise, the control itself would have to implement a multi-threaded load routine to slow loading freezes. Since you've specified this is a third party control in your comments, you may be out of luck here.

BackgroundWorker is a thread based structure. The thread-safety matter is about functions when doing simultaneous tasks. Maybe what you ask for is about winforms controls which are accessed through a unique thread, that of the user interface thread.

Ngu Soon Hui, a related task with an answer is found here. The person was using BackgroundWorker to update a textbox, same concept applies (yours is only a single worker thread).

Yes sure it does, see my updated question. I found that both thread hanged after applying the technique specified in your link. – Graviton Jan 19 '10 at 2:24 It appears that you have not put the InvokeRequired check in place and making BeginInvoke() call as displayed in the example.

The InvokeRequired ensures that you are in the correct thread, and the call with BeginInvoke() is basically calling back into the current method. I understand that document does not offer the Invoke methods so use the form object (which may be what you are doing when you call Invoke() in your second code example). Just remember, it is one thing to call BeginInvoke()... the method needs to continue to call BeginInvoke() until InvokeRequired is false.

– Jamie Altizer Jan 19 '10 at 12:38.

You need to use Control.BeginInvoke() in DoWork. This executes the delegate asynchronously and so will ensure the calling thread will not "hang". Control.Invoke() will execute the delegate on the other thread also, but will cause the calling thread to wait for it to complete.

Generally in Windows Forms you are better off using Control.BeginInvoke() wherever possible to help avoid deadlocking between threads that can occur when one thread waits for another, as with Control.Invoke(). If the "document" object inherits from System.Windows.Forms. Control, you can simply call document.

BeginInvoke(myDelegate). However if it is actually some other component that encapsulates GUI controls, it may expose some way to call BeginInvoke. Check the documentation (if any).

If there is no such ability, then unfortunately it is probably just not designed to support multi-threaded applications. It looks like you are confused about the various Invoke/BeginInvoke types (understandable). This earlier question: What is the difference between Invoke and BeginInvoke?

And Jon Skeets answer should help clarify things.

I understand, but when I called BeginInvoke, the thread hosting the document and another thread which launches a moving dialog box hanged. – Graviton Jan 19 '10 at 2:10.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions