2016-08-05 13 views
4

Wir alle kennen Methoden wie Task.Run oder Parallel.ForEach. Jeder von ihnen erstellt Aufgaben, die nach Optionen in separaten Thread oder Thread aus Thread-Pool ausgeführt wird. Aber wo ist ihr Stack? In einer Generation Heap oder gibt es einen besonderen Platz für sie?Wo ist der Aufgabenstapel in C# zugeordnet?

Zum Beispiel kann ich 1000 Aufgaben erstellen, und wo ist ihre Stapel residiert? Wird sich ihre physische Adresse irgendwann verschieben, wenn ich GC.Collect() aufruft?

+2

Dies ist ziemlich spezifisch in Bezug auf eine bestimmte CLR-Implementierung, das zugrunde liegende Betriebssystem und sogar die CPU-Architektur. Zum Beispiel bietet Windows spezielle Unterstützung für das Zuweisen (und Wachsen) von Thread-Stacks in Übereinstimmung mit der Funktionsweise der x86/x64-Speicherverwaltung. –

+0

In der Tat. Es gibt sehr wenige Anforderungen in der C# -Sprache, dass irgendwelche Stapel überhaupt existieren (wirklich nur Stapelzuordnung - es gibt nur 44 Vorkommen von "stack" in der C# -Sprachespezifikation und die Hälfte davon sind Beispielklassen, die "Stack" genannt werden) –

Antwort

3

Der Stack ist ein rein nicht verwaltetes Implementierungsdetail. Der Prozessor benötigt einen Stack, um alles zu erledigen, ohne Code kann er keinen sinnvollen Code ausführen. Es ist stark an einen Thread gebunden, ein weiteres rein unmanaged Detail auf normalen CLR-Hosts.

Es befindet sich im Speicher, wo der OS-Kernel entschied, es zuzuweisen, wenn es den Thread erstellt hat, es ist zufällig. Absichtlich willkürlich, um Malware eine harte Zeit zu geben, ist der Stack eine attraktive Möglichkeit, Daten in bösartigen Code umzuwandeln. Nicht nur der Ort ist zufällig, auch der genaue Versatz innerhalb des Stapelsegments, in dem der Stapel startet, ist zufällig.

Es bewegt sich nie, nachdem es erstellt wurde, der GC bastelt nicht damit. Es muss wissen, Objekt Wurzeln können auf dem Stapel gespeichert werden. Zuverlässige Stack-Stations sind daher eine harte .NET-Anforderung, auch der Grund dafür, dass die CLR immer dann eine gute Stack-Trace erzeugen kann, wenn ein Programm auf einer unbehandelten Exception stirbt. Das Auslaufen von Stack-Speicherplatz ist ein schwerwiegendes Problem, der Prozessor kann nicht weiter Code ausführen. Ernsthaft genug, um die Website eines Programmierers nach diesem Problem zu benennen :)

2

Aufgaben, die auf Delegaten basieren, die von einem TaskScheduler ausgeführt werden, laufen auf dem Stapel, der TaskScheduler verwendet. Der Standardplaner verwendet Threadpool-Threads. Dies sind (meist) normale .NET-Threads.

Insbesondere Task.Run erstellt eine solche Standard-Scheduler-basierte Aufgabe.

Tasks, die auf TaskCompletionSource basieren, führen keinen Code aus und benötigen keinen Stack. Sie werden basierend auf einigen externen Bedingungen wie einem IO-Abschluss oder einem Timer-Ticking abgeschlossen.

.NET hat keine integrierte Unterstützung für Heap-basierte Stapel oder "grüne Threads". In echtem Code wird man das normalerweise nicht finden.