2011-10-23 33 views
6

Tengo una aplicación escrita en wpf, que descarga algunas páginas web, analiza el código html y guarda algunos valores.Debe crear DependencySource en el mismo hilo que DependencyObject

class ListOfItems 
{  
    public List<SomeObject> ListToBind; 
    public void DownloadItems() 
    { 
     Task.Factory.StartNew(() => 
     { 
      ... 
      ... 
      if (OnDownloadCompleted != null) 
       OnDownloadCompleted(this, EventArgs.Empty); 
     } 
    } 
} 

class SomeObject 
{ 
    public string NameOfItem; 
    public MyClass Properties; 
} 

class MyClass 
{ 
    public int Percentage; 
    public SolidColorBrush Color; 
} 

Este es el modelo de objetos que estoy usando. Es una versión simplificada y no quiero que lo reorganices, hay una razón por la que lo escribí de esta manera. En ListOfItems la clase es un método que hace todo el trabajo (hay otros métodos que se usan dentro para hacer que el código sea legible) - descarga fuente, analiza y rellena ListToBind con datos, es decir,

[0] => NameOfItem = "FirstOne", Properties = {99, #FF00FF00} 
[1] => NameOfItem = "SecondOne", Properties = {50, #FFFF0000} 
etc. 

Como se puede ver, cuando este método DownloadItems completa su trabajo, se eleva OnDownloadCompleted evento. En el hilo principal se siguiente código

void listOfItems_OnDownloadCompleted(object sender, EventArgs args) 
{ 
    dataGrid.Dispatcher.Invoke(new Action(() => { 
       dataGrid.ItemsSource = ListOfItemsInstance.ListToBind; 
      })); 
} 

DataGrid en el MainWindow.xaml se llena con los valores, a causa de fragmento de código siguiente xaml.

<DataGrid Name="dataGrid" AutoGenerateColumns="False"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Header="Tag" Binding="{Binding Name}"/> 
     <DataGridTextColumn Header="Color" Binding="{Binding MyClass.Percentage}"> 
      <!--<DataGridTextColumn.CellStyle> 
       <Style TargetType="DataGridCell"> 
        <Setter Property="Background" Value="{Binding MyClass.Color}" /> 
       </Style> 
      </DataGridTextColumn.CellStyle>--> 
     </DataGridTextColumn> 
    </DataGrid.Columns> 
</DataGrid> 

Funciona bien. Pero hay este problema. Intenta descomentar el fragmento xaml comentado y obtendrás el error Must create DependencySource on same Thread as the DependencyObject..

Finalmente, mi pregunta es, ¿cómo evitar este error?

EDIT:

Se debe tener este aspecto en el final. Esta imagen está tomada de MS Excel y coloreada en Adobe Photoshop.

example

Respuesta

22

El SolidColorBrush es un Freezable que es un Objeto de Dispatcher derivado. DispatcherObjects tiene afinidad por el hilo, es decir, solo se puede usar/interactuar con el hilo en el que se creó. Sin embargo, los Freezables ofrecen la posibilidad de congelar una instancia. Esto evitará cualquier cambio adicional en el objeto pero también liberará la afinidad del hilo. Entonces puede cambiarlo para que su propiedad no almacene un DependencyObject como SolidColorBrush y simplemente almacene el Color. O puede congelar el SolidColorBrush que está creando utilizando el método Freeze.

+0

Gracias por esta explicación. La segunda respuesta a esta pregunta probablemente sea del mismo modo, pero el problema era que no sabía, qué congelar. Ahora, cuando me dijiste que SolidColorBrush se deriva de DispatcherObject y me explicó la situación, lo hice funcionar. Gracias de nuevo, la recompensa es tuya. –

1

Creo que la forma estándar es derivar el objeto de datos de Freezable y Freeze que antes de pasarlo a otro hilo. Una vez que el objeto está congelado, ya no puede cambiarlo, por lo que no hay peligro de que se produzcan errores.

Otra opción podría ser convertir el objeto de datos en un objeto simple C# (no derivado de DispatcherObject) e implementar INotifyPropertyChanged usted mismo.

+0

Los eventos PropertyChanged no tienen necesariamente que tener lugar en el hilo de la interfaz de usuario, ya que se [calculan automáticamente en el hilo de la interfaz de usuario. [http://stackoverflow.com/a/11015784] – user1912383

+0

@ user1912383: Tienes razón, por supuesto. Pero no sabía eso hace 5 años ... – Niki

Cuestiones relacionadas