2017-04-11 2 views
2

Ich bin ein wenig neu in C# Threading, aber ich habe eine Codebasis geerbt, die ziemlich viel davon tut. Ich schaue mir einige Multithread-Code-Segmente an, die logisch hintereinander laufen. Hier ein Beispiel:Parallel ForEach mit dem aktuellen Synchronisationskontext

// Draw the nodes. 
var factory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext()); 
var drawingTasks = new List<Task>(nodePoints.Count); 
Parallel.ForEach(nodePoints, nodePoint => 
{ 
    Task task = factory.StartNew(() => DrawNode(token, nodePoint, groupList), token, TaskCreationOptions.None, factory.Scheduler); 
    if (task != null) 
     drawingTasks.Add(task); 
}); 

await factory.ContinueWhenAll(drawingTasks.ToArray(), result => 
{ 
    _event.Publish(new MapNodesDrawnEvent()); 
}); 

Debuggen der Anwendung zeigt dies auf der Haupt-Thread ausgeführt wird, welche ich annehme ist auch der UI-Thread. Da die neuen Threads den aktuellen Synchronisationskontext verwenden, werden nicht alle diese Tasks nacheinander auf dem Hauptthread ausgeführt. Wenn ja, ist es sinnvoll, dies zu tun?

Antwort

3
  1. List<Task> ist nicht Thread sicher, können Sie es nicht in einem Parallel.ForEach verwenden, ohne Verriegelung (auch wenn Sie die Liste vorgesiebt es noch nicht sicher ist).
  2. Wenn Sie nur einen neuen Thread mit einer TaskFactory starten, gibt es keinen Grund, dies parallel zu tun. Aufruf von StartNew ist unglaublich schnell, so dass es keine Notwendigkeit gibt.
  3. Die Parallel Klassen verwenden den aufrufenden Thread als eine der Worker-Threads, so dass es möglich ist, dass der aufrufende Thread in einem Parallel.ForEach
  4. Sie TaskScheduler.FromCurrentSynchronizationContext() genannt verwendet werden könnte, die von einem Thread aufgerufen, wenn das seinen SynchronizationContext Satz hatte, Dies ist wahrscheinlich der UI-Thread oder ein Hintergrundthread mit SynchronizationContext.SetSynchronizationContext( genannt, wird dazu führen, dass Tasks, die mit diesem Scheduler gestartet werden, aus dem UI-Thread ausgeführt werden.

Das einzige, was der entsandte Code, den Sie gibt Ihnen die Arbeit würden Schlange stehen an bis zum Ende der Nachrichten-Warteschlange verarbeitet werden würde (wenn Sie Problem behoben 1 so nolonger Buggy es war). Dies kann nützlich sein, wenn Sie die Arbeit später verschieben möchten, aber Dispatcher.BeginInvoke ist ein viel besserer Weg, es zu tun.

Verwandte Themen