I start a few threads that work in background. They have their jobs, and they raise events that I consume in the ViewModel, and changes the UI.
For example, look at this method from a ViewModel:
private async void Start() { try { IncrementAsyncCalls("Validando..."); var publishingPointAction = await Task.Run<IPublishingPointAction>(() => driverService.VerifyIfCanStart()); IncrementAsyncCalls("Liberando publishing points..."); await Task.Run(() => publishingPointAction.Deallocate()); IncrementAsyncCalls("Reservando publishing points..."); var startable = await Task.Run<IStartable>(() => publishingPointAction.Allocate()); IncrementAsyncCalls("Iniciando o encoder..."); Task.Run(() => startable.Start()); } catch (FreeChannelNotFoundException ex) { messageService.ShowWarning(ex.Message); navigationService.NavigateTo(RegionNames.PopupRegion, ViewNames.ProfileSelection); } catch (ScheduleNotSelectedException ex) { messageService.ShowWarning(ex.Message); //TODO: selecionar a ABA das Agendas. } catch (Exception ex) { messageService.ShowError(ex); } finally { ResetAsyncCalls(); } }
Ultimately, I'm starting a thread in the "startable.Start()" call. The following code shows the events I'm consuming (also in the ViewModel):
private void SetupDriverEvents() { driverService.OnEncoderStatusChanged += (s, e) => { EncoderStatus = e; }; driverService.OnTransmitterStatusChanged += (s, e) => { TransmitterStatus = e; }; driverService.OnEncoderTimeChanged += (s, e) => { EncoderTime = e; }; driverService.OnWaiting += (s, e) => { Waiting = e; Transmit.RaiseCanExecuteChanged(); }; driverService.OnError += (s, e) => { application.Dispatcher.BeginInvoke((Action)(() => { messageService.ShowWarning(e); })); }; }
EncoderStatus, TransmitterStatus, EncoderTime are all properties of the ViewModel that I bind to the UI. When the application reaches those events handlers, the thread is not the UI thread, right? And, as you can see, I'm not using Dispatcher to update the property. The code works without the Dispatcher. But why is that? Shouldn't the application fail to update the UI in the another thread?
What is more interesting, is that I need to use Dispatcher in the ShowWarning, because if I don't, an exception is raised telling me that it can't do that in a different thread.
Although the code works, I'm experiencing some delay to update the UI. I mean, there are times that the EncoderTime takes too long to update, it's like is waiting for others updates to occur before it can actually change the UI.
Take a look at WPF FlashMessage
About.me