views:

168

answers:

3

Hi, The following method does not apply the wpf changes (background = red) until the 2nd method (DoWork) exits:

private void change()
{
    Background = Brushes.Red;
    Dispatcher.BeginInvoke((Action) DoWork);
}

DoWork() takes several seconds to run and I don't really want to put it into a thread, as this code will be used in several places and will probably interact will the Dispatcher thread at various intervals. I've tried calling the Invalidate...() methods, but to no avail. The BeginInvoke() was added to see if the delay would allow the background change to be applied before the logic was called. Typically, the logic would be part of this method. Btw, most of the logic is performed on a different thread and shouldn't block the Dispatcher thread?!

Can someone please help? Thanks

+3  A: 

The "Dispatcher" thread is the UI thread.

When you call Dispatcher.BeginInvoke((Action) DoWork);, you're basically blocking the UI thread until DoWork exits, since it's running on the UI thread.

This will prevent the UI from updating, hence you don't see the background change.

You really should consider moving DoWork onto a background thread, either via the ThreadPool directly, a BackgroundWorker, or some other means. That would completely correct this problem, and prevent you from blocking the UI thread for a "few seconds" (which will happen if you run this using the Dispatcher's threading).

Reed Copsey
Doesn't Dispatcher.Invoke() block the code and not BeginInvoke()? Using a thread implies that you should use threads for all processing behind the ui, which sounds very tedious. Does the WPF engine not cater for this by being mutlithreaded in the background? Anyway, sounds like I have to dump the logic into a thread. Thanks for your help...
Colin Rouse
@Colin: If you're on the UI thread, both will block. Using the Dispatcher causes your code to run **on the UI thread**, that's the purpose. If you want this to run in the background thread, you'd use ThreadPool.QueueUserWorkItem, not Dispatcher (Dispatcher's for the opposite purpose - if you're on a background thread, and want to run something on the UI thread, you use Dispatcher)
Reed Copsey
thanks, that works
Colin Rouse
A: 

I tried to use the background threaded approach, however this raises problem where changes to the UI are attempted outside of the Dispatcher thread. For example, variables bound to user controls are fired in the DoWork() method, which throw exceptions due to not being executed in the Dispatcher thread. The above approach also means that any change to the UI from DoWork() must be wrapped in a Dispatcher.(Begin)Invoke() call, which means bloated code. There must be a different way to do this?!

Thanks

Colin Rouse
You have three choices: 1) run the long-running task on the UI thread and let the UI block and wait, 2) run it on another thread and deal with cross-threading issues when you try to update the UI during the task, 3) don't update the UI during the task. If you decide you have to go with #2, the issues you're encountering are inherent. Using `BackgroundWorker` helps somewhat; it gives you a consistent way to isolate UI-updating code in the progress-reporting event. But updating data-bound property values in the background thread? No.
Robert Rossney
An easy way to solve this is to create a view model, bind the UI to it, and update the view model from the background thread. That way WPF's data binding can deal with all the threading issues. Directly updating the UI from code without going through a view model is always a bad idea anyway.
Ray Burns
A: 

for communication between thread we haev Dispatcher class in WPF

Dispatcher.Invoke(DispatcherPriority.Normal, (NoArgDelegate)delegate { ------ });

prakash