2016-07-01 6 views
0

Meine Situation passieren:Wie ein GeometryCollection zwischen Threads

Ich möchte eine Karte zeichnen, die aus verschiedenen Schichten besteht.

Bisher verwende ich ein ItemsControl alle Schichten anzuzeigen:

<ItemsControl ItemsSource="{Binding Layers}" 
       ItemTemplate="{StaticResource LayerViewTemplate}"> 
    <ItemsControl.ItemsPanel> 
     <ItemsPanelTemplate> 
      <Grid/> 
     </ItemsPanelTemplate> 
    </ItemsControl.ItemsPanel> 
</ItemsControl> 

Die Vorlage i das sieht aus wie verwenden:

<DataTemplate x:Key="LayerViewTemplate" 
       DataType="{x:Type data:InformationLayer}"> 
     <Path StrokeThikness="{Binding W}" 
      Stroke="Black" 
      Data = {Binding Data}/> 
    </DataTemplate> 

Wie Sie sehen können, die Klasse InformationLayer enthält alle die Daten einer Schicht. Dies schließt die Eigenschaft ein:

public GeometryGroup Data { get; protected set; } 

Erzeugung der Schichten ist ein langwieriger Prozess zäh. Ich muss eine Reihe von Dateien usw. lesen. Deshalb würde ich es gerne in einer asynchronen Funktion machen.

Das Problem:

GeometryGroup Objekte zu dem Thread gehören, die sie geschaffen haben. Also, wenn ich einen anderen Thread verwenden, um meine Ebenen zu erstellen, werden sie zu diesem Thread gehören. Ich möchte, dass sie zu meinem Hauptthread gehören, weil ich sie als eine verbindliche Quelle verwenden möchte. Gibt es eine Möglichkeit, die GeometryGroup von einem Thread zum anderen zu verschieben?

Bisher sieht die Funktion zum Generieren meiner Ebenen folgendermaßen aus: aber die letzte Zeile löst eine Ausnahme aus, weil wpf nicht an ein Objekt binden will, das in einem anderen Thread generiert wurde.

protected async void generateLayers() 
    { 
     var progress = new Progress<RefreshLayersProgressReport>(ReportLayerProgress); 
     var ans = await Task.Run(() => refreshLayers(progress)); 

     Layers = ans; 
    } 
+0

Führen Sie einen separaten Prozess, so dass Sie entweder alle Daten an den Thread am Anfang des Threads übergeben müssen oder eine Pipe verwenden. Eine einfache Pipe kann mit einer MemoryStream-Klasse verwendet werden. – jdweng

Antwort

1

GeometryGroup aus Freezable abgeleitet. Es sollte daher cross-thread zugänglich sein nach dem Aufruf seiner Freeze() Methode.

Vom Threadsicherheit Abschnitt auf der Freezable Seite:

Wenn die IsFrozen-Eigenschaft ist falsch, ein Freezable-Objekt kann nur aus dem Thread zugegriffen werden, auf dem sie erstellt wurde. Wenn Sie versuchen, von einem anderen Thread auf zuzugreifen, wird eine InvalidOperationException ausgelöst. Die Methoden Dispatcher.Invoke und Dispatcher.BeginInvoke bieten Unterstützung für das Marshalling zum richtigen Thread.

Wenn ihre IsFrozen-Eigenschaft wahr ist, sind Freezable-Objekte free-threaded. Weitere Informationen finden Sie unter Übersicht über Freezable-Objekte.

+0

Ahhh Danke. Da ich meine 'GeometryGroup' nach der Erstellung nicht ändern muss, funktioniert das perfekt für mich. –

Verwandte Themen