2010-12-09 37 views
8

tengo el siguiente método en una clase base que implementa System.ComponentModel.INotifyPropertyChanged:.NET No se puede realizar esta operación mientras que el procesamiento se suspende despachador

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); 
    } 
} 

En ocasiones, me gustaría tener la siguiente excepción conectado a presentar :

Tipo: System.InvalidOperationException, mscorlib, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089 Mensaje: No se puede realizar esta operación mientras se suspende el procesamiento del despachador. Fuente: WindowsBase enlace Ayuda: datos: System.Collections.ListDictionaryInternal TargetSite: PushFrame Vacío (System.Windows.Threading.DispatcherFrame) Seguimiento de la pila: en System.Windows.Threading.Dispatcher.PushFrame (marco DispatcherFrame) en System.Windows.Threading.DispatcherOperation.Wait (TimeSpan timeout) en System.Windows.Threading.Dispatcher.InvokeImpl (prioridad de DispatcherPriority, TimeSpan timeout, método Delegate, Object args, Boolean isSingleParameter) en System.Windows.Threading.Dispatcher. Invoke (prioridad de DispatcherPriority, método Delegate) en OCC600.Infrastructure.Dictionary.BusinessEntities.Observable.RaisePropertyChangedEventSynchronous (String propertyName)

Si uso Dispatcher.BeginInvoke para actualizar la interfaz de usuario, no obtengo estas excepciones. Pero descubrí que realizar actualizaciones con BeginInvoke no es confiable ya que a veces estos cambios no se reflejan en la interfaz de usuario.

¿Cómo soluciono este problema?

Respuesta

8

Supongo que está en un hilo de fondo y está intentando subir su evento PropertyChanged en el hilo de la interfaz de usuario. Creo que WPF maneja el cambio de hilo para usted; no deberías tener que hacer esto.

Aquí hay un código que escribí. 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)); 
     } 
    } 
    } 
} 
+1

Gracias, gracias. Esto debería simplemente cosas mucho. Para actualizar colecciones, sin embargo, tengo que hacer un dispatcher.invoke en el método CollectionView.Refresh(), de lo contrario se lanza una excepción. –

+0

Para eso, debe usar Dispatcher.BeginInvoke. No hay otra solución, ya que necesita estar en el hilo del despachador y no hay una manera confiable de saber cuándo se suspende al despachador. –

+0

Gracias. Comprobado nuevamente y estoy usando BeginInvoke para actualizar las colecciones. –

Cuestiones relacionadas