Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET Cannot perform this operation while dispatcher processing is suspended

Tags:

.net

wpf

I have the following method in a base class that implements System.ComponentModel.INotifyPropertyChanged:

protected virtual void RaisePropertyChangedEventSynchronous(string propertyName)
{                    
    try
    {
        if (PropertyChanged != null)
        {
            Delegate[] delegates = this.PropertyChanged.GetInvocationList();
            foreach (PropertyChangedEventHandler handler in delegates)
            {                      
                try
                {
                    DispatcherObject dispatcherInvoker = handler.Target 
                        as DispatcherObject;
                    if (dispatcherInvoker != null)
                    {                                
                        dispatcherInvoker.Dispatcher.Invoke(DispatcherPriority.Normal, 
                            new Action(delegate
                        {
                            handler(this, new PropertyChangedEventArgs(propertyName));
                        }));
                    }
                    else
                    {
                        handler(this, new PropertyChangedEventArgs(propertyName));
                    }
                }
                catch (Exception ex)
                {                     
                    ExceptionPolicy.HandleException(ex, 
                        ExceptionHandlingPolicyNames.LogPolicy);
                }
            }
        }
    }
    catch (Exception ex)
    {
         ExceptionPolicy.HandleException(ex, ExceptionHandlingPolicyNames.LogPolicy);
    }
}

On occasion, I would get the following exception logged to file:

Type : System.InvalidOperationException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Message : Cannot perform this operation while dispatcher processing is suspended. Source : WindowsBase Help link : Data : System.Collections.ListDictionaryInternal TargetSite : Void PushFrame(System.Windows.Threading.DispatcherFrame) Stack Trace : at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame) at System.Windows.Threading.DispatcherOperation.Wait(TimeSpan timeout) at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Boolean isSingleParameter) at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method) at OCC600.Infrastructure.Dictionary.BusinessEntities.Observable.RaisePropertyChangedEventSynchronous(String propertyName)

If I use Dispatcher.BeginInvoke to update the UI, I do not get these exceptions. But I have found out that performing updates using BeginInvoke is not reliable as sometimes these changes are not reflected on the user interface.

How do I solve this one?

like image 857
Klaus Nji Avatar asked Dec 09 '10 21:12

Klaus Nji


1 Answers

I presume you're on a background thread and are trying to raise your PropertyChanged event on the UI thread. I think WPF handles the thread change for you; you shouldn't have to do this.

Here's some code I wrote. XAML:

<Window x:Class="WpfApplication2.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
  <Grid>
    <TextBlock Text="{Binding Value}" />
  </Grid>

C#:

public partial class MainWindow : Window {
  public MainWindow() {
    InitializeComponent();

    this.DataContext = new Backgrounder();
  }

  class Backgrounder : INotifyPropertyChanged {
    int value = 0;
    public Backgrounder() {
      ThreadPool.QueueUserWorkItem(o => {
        while (true) {
          this.value++;
          Notify("Value");
          Thread.Sleep(TimeSpan.FromSeconds(1));
        }
      });
    }

    public int Value { get { return this.value; } }

    public event PropertyChangedEventHandler PropertyChanged;

    void Notify(string property) {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null) { 
        handler(this, new PropertyChangedEventArgs(property)); 
      }
    }
  }
}
like image 197
John Doty Avatar answered Sep 26 '22 07:09

John Doty