Warum kann eine lokale variable zugegriffen werden, die in einem anderen thread erstellt in der gleichen Klasse?
Konnte ich nicht wirklich finden, alles, was auf genau dieses Thema, also bitte führe mich in Richtung die richtige Richtung, wenn eine Frage bereits vorhanden ist.
Von dem, was ich gelernt habe über .NET, es ist nicht möglich, den Zugriff auf Variablen in verschiedenen threads (bitte korrigiert mich falls diese Aussage falsch ist, ist es genau das, was ich irgendwo gelesen habe).
Nun in diesem codesample, aber es scheint dann, dass es nicht funktionieren sollte:
class MyClass
{
public int variable;
internal MyClass()
{
Thread thread = new Thread(new ThreadStart(DoSomething));
thread.IsBackground = true;
thread.Start();
}
public void DoSomething()
{
variable = 0;
for (int i = 0; i < 10; i++)
variable++;
MessageBox.Show(variable.ToString());
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void SomeMethod();
{
MyClass mc = new MyClass();
}
}
Wenn ich SomeMethod()
sollte nicht .NET eine Ausnahme, weil das erstellte Objekt mc
läuft in einem anderen thread als dem thread erstellt innerhalb der mc
-Initialisierer und dieser neue thread versucht Zugriff auf die lokalen Variablen der mc
?
Den MessageBox
zeigt 10
wie (nicht) erwartet, aber ich bin nicht sicher, warum das funktionieren sollte.
Vielleicht ich wusste nicht, was Sie suchen, aber keine threading-Thema, die ich finden konnte, würde dieses Problem zu beheben, aber vielleicht ist meine Vorstellung von Variablen und threads ist falsch.
InformationsquelleAutor der Frage phil13131 | 2013-09-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Diese Aussage ist völlig falsch, so betrachten Sie diese Ihre Korrektur.
Du wahrscheinlich irgendwo gelesen, dass lokale Variablen nicht zugegriffen werden kann, über verschiedene threads. Diese Aussage ist auch falsch, sondern wird allgemein angegeben. Die richtige Aussage ist, dass lokale Variablen, die nicht
yield return
oderyield break
)nicht für den Zugriff durch mehrere threads. Und auch diese Behauptung ist ein bisschen heikel; es gibt Möglichkeiten zu tun, die mit Zeiger und
unsafe
code-Blöcke, aber es ist eine sehr schlechte Idee, zu versuchen, dies zu tun.Ich beachten Sie auch, dass Ihre Frage bittet um lokale Variablen, aber dann zeigt ein Beispiel eines Feld. Ein Feld ist per definition nicht eine lokale variable. Eine lokale variable ist per definition lokal zu einer Methode, die Körper. (Oder Konstruktor-Körper, indexer Körper, etc.) Stellen Sie sicher, Sie sind klar. Das wesentliche Merkmal eines lokalen ist nicht, dass es "auf dem stack" oder so etwas; die "lokalen" Teil des lokalen ist, dass sein name ist nicht sinnvoll außerhalb des methodentexts.
Im Allgemeinen Fall: eine variable ist eine Lagerort , bezieht sich auf Speicher. Ein thread ist eine point-of-control in einem Prozessund alle threads in einem Prozess teilen sich den gleichen Speicher, das ist, was macht Sie threads und nicht Prozesse. So im Allgemeinen, alle Variablen zugegriffen werden können, indem mehrere threads zu allen Zeiten und in allen Bestellungen, es sei denn, irgendein Mechanismus ist, um zu verhindern, dass.
Lassen Sie mich sagen, dass wieder einmal nur um sicherzustellen, dass es ist absolut glasklar in Ihrem Kopf: die richtige Art zu denken, ein single-threaded Programm ist, dass alle Variablen stabiles sei denn, etwas macht, Sie sich verändern. Der richtige Weg zu denken, über ein multi-threaded Programm, das alle Variablen sind mutiert ständig in keiner bestimmten Reihenfolgees sei denn, etwas hält Sie noch immer oder so gut bestellt. Dies ist der grundlegende Grund, warum die shared-memory-Modell von multithreading ist so schwerund daher, warum sollten Sie es vermeiden.
In Ihrem speziellen Beispiel, beide threads haben Zugriff auf
this
und somit beide threads sehen kann, die variablethis.variable
. Sie implementiert haben keine Mechanismen, um das zu verhindern, und somit beide threads können schreiben und Lesen, dass die Variablen in beliebiger Reihenfolge, unterliegt nur sehr wenige Einschränkungen in der Tat. Einige Mechanismen, die Sie haben könnte, umgesetzt zu zähmen, dieses Verhalten sind:ThreadStatic
. Dadurch wird eine neue variable erzeugt werden, die jedem thread.volatile
. Dabei gelten einige Einschränkungen, wie man liest und schreibt, kann beobachtet werden, bestellt werden, und außerdem erlegt bestimmte Beschränkungen auf Optimierungen durch den compiler oder die CPU könnte zu unerwarteten Ergebnissen führen.lock
- Anweisung um jeder Verwendung der variable.Es sei denn, Sie haben eine tief Verständnis von multithreading und Prozessor-Optimierungen, empfehle ich vor jeder option, mit Ausnahme der letzteren.
Nehmen wir nun an, Sie habe sicherstellen wollen, dass der Zugriff auf die variable failed auf einem anderen thread. Man könnte den Konstruktor erfassen die thread-ID des thread erstellen und verstauen es Weg. Dann könnten Sie den Zugriff auf die variable über eine Eigenschaft getter/setter, wo der getter-und setter-überprüfen Sie die aktuelle thread-ID, und eine Ausnahme werfen, wenn es nicht der gleiche wie der ursprüngliche thread-ID.
Im wesentlichen, was dieser tut, ist Rollen Sie Ihre eigenen single threaded apartment-threading-Modell. Eine "single threaded apartment" - Objekt ist ein Objekt, das nur zugegriffen werden kann, rechtlich auf den thread, in dem es erstellt. (Sie kaufen einen Fernseher, setzen Sie ihn in Ihrer Wohnung, nur Menschen in Ihre Wohnung zu dürfen um zu sehen wie die TV.) Die details des single-threaded-apartments vs Multithread-apartments vs free-threading kompliziert; siehe diese Frage für mehr hintergrund.
Können Sie uns erklären, STA und MTA?
Dies ist, warum, zum Beispiel, müssen Sie nie den Zugriff auf ein UI-element, das Sie erstellen, die auf dem UI-thread aus einem worker-thread; die Elemente der Benutzeroberfläche STA-Objekte.
InformationsquelleAutor der Antwort Eric Lippert
Das ist nicht korrekt. Eine variable kann von überall abgerufen werden, ist es im Rahmen.
Müssen Sie vorsichtig sein, wenn Sie Zugriff auf die gleiche variable von mehreren threads, da jeder thread handeln können die variable auf eine nicht-deterministische Zeit, was zu subtilen, schwer zu beheben bugs.
Es ist eine hervorragende Webseite, die deckt threading in .Die NETTO-von den Grundlagen bis zu fortgeschrittenen Konzepten.
http://www.albahari.com/threading/
InformationsquelleAutor der Antwort Eric J.
Ich bin ein bisschen spät, und die Antwort @Eric J. gab, ist wunderbar und auf den Punkt.
Ich will einfach nur, um ein bisschen von Klarheit zu einer anderen Frage, in der Ihre Wahrnehmung der Themen und Variablen.
Sagte Sie dies in Ihrer Frage ist der Titel "variable zugegriffen werden, die in einem anderen thread".
Hinzu kommt, dass, ist die Tatsache, dass in Ihrem code, Sie greifen auf Ihre variable von genau 1 thread das ist der thread, der erzeugt wird, hier:
All diese Dinge machten mir klar, dass Sie erschrocken waren, dass ein thread von der anderen, die tatsächlich erstellt die Instanz von
MyClass
etwas aus dem inneren der Instanz.Folgende Fakten sind wichtig für eine klarere Sicht auf das, was multithreading ist (es ist einfacher, dass Sie denken):
BEARBEITEN
Sehe ich die Worte thread-Sicherheit erschien auf diesen thread Antworten.
Im Falle dass Sie sich vielleicht Fragen, was diese Worte bedeuten, empfehle ich diesen tollen Artikel von @Eric Lippert:
http://blogs.msdn.com/b/ericlippert/archive/2009/10/19/what-is-this-thing-you-call-thread-safe.aspx
InformationsquelleAutor der Antwort Eduard Dumitru
Nein, Sie haben es rückwärts, Daten zugegriffen werden, solange es noch im Rahmen.
Müssen Sie zum Schutz gegen das entgegengesetzte problem, zwei threads den Zugriff auf die gleichen Daten in der gleichen Zeit, die aufgerufen wird, eine race-condition. Sie können eine Synchronisierung Technik wie
lock
um dies zu verhindern, aber wenn falsch verwendet kann es zum deadlock.Lesen C# Threading in .NET für ein tutorial.
InformationsquelleAutor der Antwort Karl Anderson
Speicherplätze sind nicht isoliert in einem einzigen thread. Es wäre wirklich unpraktisch, wenn Sie waren. Arbeitsspeichers in der CLR wird nur vereinzelt auf die Anwendungsdomäne Grenze. Das ist, warum es einer separaten Instanz für jede statische variable pro AppDomain. Allerdings threads sind nicht gebunden an eine bestimmte Anwendungs-Domäne. Sie können code ausführen, der in mehr als einer Anwendung-domain-oder "none" (unmanaged code). Was Sie nicht tun können, ist die Ausführung von code aus mehr als einer Anwendungsdomäne bei der gleichen Zeit. Was dies bedeutet ist, dass ein thread kann nicht gleichzeitig bestimmt haben den Zugang zu Daten-Strukturen aus zwei verschiedenen Bereichen Anwendung. Das ist, warum Sie haben, zu nutzen, Marshalling-Techniken (über
MarshalByRefObject
zum Beispiel) oder Kommunikationsprotokolle verwendet werden, wie .NET-Remoting oder WCF-Zugriff auf Daten-Strukturen aus einer anderen Anwendungsdomäne.Betrachten Sie die folgenden unicode-Kunst-Diagramm eines Prozesses, der das hosting der CLR.
Können Sie sehen, dass jeder Prozess kann mehr als eine Anwendungsdomäne und ein thread kann die Ausführung von code aus mehr als nur einer von Ihnen. Ich habe auch versucht, illustrieren die Tatsache, dass ein thread ausführen, der nicht verwalteten code als auch durch das zeigen seiner Existenz außerhalb der linken und rechten AppDomain-Blöcke als gut.
Also im Grunde ein thread triviale und nicht-triviale Zugriff auf beliebige Datenstrukturen in der gleichen Anwendungsdomäne, dass es derzeit ausführen. Ich bin mit dem Begriff "trivial" hier zu gehören Speicherzugriffe (Datenstrukturen, Variablen, etc.) über public, protected oder internal Mitglieder von einer Klasse zur anderen. Ein thread in keiner Weise verhindert, dass dies geschieht. Jedoch, mit der spiegelung könnte man immer noch Zugang selbst zu den private member einer anderen Klasse. Das ist das, was ich Vorschlage, nicht-triviale Zugang. Ja, es geht um ein bisschen mehr Arbeit auf Ihrem Teil, aber es ist sonst nichts besonderes Los, sobald Sie abgeschlossen haben, die Reflexion nennt (was übrigens erlaubt sein muss, durch die code access security, aber das ist ein anderes Thema). Der Punkt ist, dass ein thread hat Zugriff auf so ziemlich alle Speicher in der gleichen Anwendungsdomäne, die es ausführt.
Der Grund, warum ein thread hat Zugriff auf fast alles, was in die gleiche Anwendungsdomäne ist, denn es wäre wahnsinnig restriktiv, wenn es nicht. Entwickler müssten streckte eine Menge von zusätzlichen Aufwand, um Daten auszutauschen Strukturen zwischen den Klassen bei der Arbeit in einer Multithread-Umgebung.
Also zusammenfassend die wichtigsten Punkte:
1Auch die Singularity-Betriebssystem erscheint direkt anzeigen .NET-threads auf Betriebssystem und hardware.
InformationsquelleAutor der Antwort Brian Gideon