Erstellen müssen DependencySource auf denselben Thread DependencyObject
Ich habe eine Anwendung geschrieben in wpf, die downloads einige Webseiten, analysiert html-code und speichert einige Werte.
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;
}
Dies ist das Objekt, das Modell, das ich verwende. Es ist die vereinfachte version und ich will nicht, Sie zu reorganisieren, gibt es einen Grund, warum ich schrieb es auf diese Weise. In ListOfItems
Klasse ist die Methode, die macht die ganze Arbeit (es gibt einige andere Methoden, die verwendet, um code lesbar) - downloads-Quelle, analysiert und füllt ListToBind
mit Daten -, f -.e.
[0] => NameOfItem = "FirstOne", Properties = {99, #FF00FF00}
[1] => NameOfItem = "SecondOne", Properties = {50, #FFFF0000}
etc.
Wie Sie sehen können, wenn Sie diese Methode DownloadItems
beendet seine Arbeit, OnDownloadCompleted
Ereignis ausgelöst wird. In der Haupt-thread folgenden code
void listOfItems_OnDownloadCompleted(object sender, EventArgs args)
{
dataGrid.Dispatcher.Invoke(new Action(() => {
dataGrid.ItemsSource = ListOfItemsInstance.ListToBind;
}));
}
DataGrid auf die MainWindow.xaml
ist mit Werten gefüllt, da der folgende xaml-code-snippet.
<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>
Funktioniert es Prima. Aber es gibt dieses problem. Versuchen Sie, kommentieren Sie kommentiert xaml-Ausschnitt und erhalten Sie Must create DependencySource on same Thread as the DependencyObject.
Fehler.
Schließlich, meine Frage ist, wie man diesen Fehler vermeiden?
EDIT:
Es sollte so Aussehen am Ende. Dieses Bild ist genommen von MS Excel und farbig in Adobe Photoshop.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den SolidColorBrush ist ein Freezable was ist eine abgeleitete DispatcherObject. DispatcherObjects haben, die thread-Affinität - ich.e es können nur verwendet werden/mit interagiert über den thread, in dem es erstellt wurde. Freezables jedoch bieten die Möglichkeit zum einfrieren einer Instanz. Dies wird verhindern, dass weitere änderungen an dem Objekt, aber es wird auch lassen Sie die thread-Affinität. So können Sie entweder ändern Sie es so, dass Ihre Immobilie ist nicht die Speicherung eines DependencyObject wie SolidColorBrush und statt speichern nur die Farbe. Oder Sie können einfrieren des SolidColorBrush, die Sie erstellen mithilfe der Freeze Methode.
Ich denke, dass der standard-Weg ist die Daten ableiten Objekt aus
Freezable
undFreeze
es vor der übergabe zu einem anderen thread. Sobald das Objekt eingefroren ist, kann man nicht ändern es nicht mehr, also gibt es keine Gefahr von threading-bugs.Weitere option könnte sein, das Daten-Objekt ist eine einfache C# - Objekt (nicht abgeleitet von
DispatcherObject
) und die Durchführung derINotifyPropertyChanged
selbst.Seine nicht genug, um Ihre
dataGrid.ItemsSource
auf dem Haupt-thread. Sie müssen erstellen, die jedes Element auf den Haupt-thread.So etwas wie: