Async Process Runs but UI Doesn't Update

Topics: Prism v4 - WPF 4
Oct 21, 2010 at 9:19 PM

I have a busy indicator in my shell. I have an event that I fire anywhere in the app that will change IsBusy to true. I have a collapsed border that is bound to the IsBusy property. In one of my modules, I fire the WaitScreenEvent with true, run my async process using Reactive Extensions. I'm using a Scheduler option of Dispatcher. I can see from my debug output, IsBusy goes true, items are added to my observable collection, and then IsBusy goes false. However, the border never updates. The subscription on the event is ThreadOption.BackgroundThread. I observed the same behavior when I had it at ThreadOption.UIThread too. Thanks.

Oct 22, 2010 at 2:36 PM

Not sure if this helps you or not, but I was having the same problem at first. I'm assuming that what I have below is similar to what you have. If so, the part that was necessary is below, which I had to put in my ViewModel


ProgressBarEvent progressBarEvent = _eventAggregator.GetEvent<ProgressBarEvent>();
progressBarEvent.Subscribe(OnProgressBarEvent, Microsoft.Practices.Prism.Events.ThreadOption.BackgroundThread);



  private void OnProgressBarEvent(object args)
                ProgressBarActionArgs pargProgressBarAction = args as ProgressBarActionArgs;
                if (pargProgressBarAction == null)
                    throw new Exception("Arguments passed into OnProgressBarEvent should only be of type 'ProgressBarActionArgs'");

                UpdateStatusBar(pargProgressBarAction.StatusMessage, pargProgressBarAction.ErrorMessage, pargProgressBarAction.ProgressBarAction);



private void UpdateStatusBar(string statusMessage, string errorMessage, ProgressBarEnum progressBarAction)
                ThreadStart start = delegate()
                    DispatcherOperation op = Dispatcher.BeginInvoke(
                        new Action<string, string, ProgressBarEnum>(SetStatus),
                        statusMessage, errorMessage, progressBarAction);

                    DispatcherOperationStatus status = op.Status;
                    while (status != DispatcherOperationStatus.Completed)
                        status = op.Wait(TimeSpan.FromMilliseconds(1000));
                        if (status == DispatcherOperationStatus.Aborted)
                            // Alert Someone

                new Thread(start).Start();

-------------------View Model Code--------------------------

void OKClicked(object sender, EventArgs e)
            base.UpdateStatusBar(ProgressBarEnum.Start, "Searching");

            mWorker = new System.ComponentModel.BackgroundWorker();
            mWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(mWorker_DoWork);
            mWorker.WorkerReportsProgress = true;
            mWorker.WorkerSupportsCancellation = true;
            mWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(mWorker_RunWorkerCompleted);
void mWorker_DoWork(object sender, DoWorkEventArgs e)
void mWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            base.UpdateStatusBar(ProgressBarEnum.Stop, string.Format("{0} Records Returned", SearchResults.Count.ToString("#,##0")));
The one caveat to this is that I didn't feel like messing with the dispatcher in the RunSearch, so rather than putting the results directly in the dependency property that the UI is bound to, I put the results in a module level variable and then in the ProcessQueryResults, I pushed that into my dependency property.


Oct 22, 2010 at 9:08 PM

I played around with this before your response. I believe I essentially have the same thing:


var cycles = new ObservableCollection<Cycle>();

    item => cycles.Add(item),
    ex => EventAggregator.GetEvent<ExceptionEvent>().Publish(new ExceptionEvent(ex)),
    () => {
        Cycles = new ObservableCollection<Cycle>(cycles);


I also noticed the issue with binding and being on the same thread. That's why I assign my local collection to the dependency property in the Subscribe's "finally".  Here is my service:

public IObservable<Cycle> GetCycles(int companyId) {
            () => new CycleInvoicingModelContainer(),
            container => {
                container.Connection.ConnectionString = _connectionService.GetEntityConnectionString(companyId,
                return container.Cycles.Where(c => c.Posted == "Y").OrderBy(c => c.Creation_Date).ToObservable(Scheduler.ThreadPool);