7 Stimmen

verschiedene Threads, die auf den MemoryStream zugreifen

Es gibt einen Teil des Codes, der Daten in ein MemoryStream-Objekt direkt in dessen Datenpuffer schreibt, indem er GetBuffer() aufruft. Er verwendet und aktualisiert auch die Eigenschaften Position und SetLength() entsprechend.

Dieser Code funktioniert in 99,9999 % der Fälle richtig. Buchstäblich. Nur alle 100.000 Iterationen wird er kotzen. Das spezifische Problem ist, dass die Position-Eigenschaft von MemoryStream plötzlich Null anstelle des entsprechenden Wertes zurückgibt.

Es wurde jedoch Code hinzugefügt, der auf die 0 prüft und eine Ausnahme auslöst, die ein Protokoll der MemoryStream-Eigenschaften wie Position und Länge in einer separaten Methode enthält. Diese geben den richtigen Wert zurück. Eine weitere Ergänzung der Protokollierung innerhalb derselben Methode zeigt, dass in diesem seltenen Fall die Position nur innerhalb dieser speziellen Methode Null ist.

Ja. Offensichtlich muss es sich um ein Threading-Problem handeln. Und höchstwahrscheinlich ein Compiler-Optimierungsproblem.

Es liegt jedoch in der Natur dieser Software, dass sie nach "Tasks" mit einem Scheduler organisiert ist, so dass ein beliebiger von mehreren tatsächlichen Betriebssystem-Threads diesen Code zu einem beliebigen Zeitpunkt ausführen kann - aber niemals mehr als einer gleichzeitig.

Ich vermute also, dass es normalerweise so ist, dass immer derselbe Faden für diese Methode verwendet wird und dann bei einer seltenen Gelegenheit ein anderer. (Ich habe gerade die Idee, diese Theorie zu testen, indem ich die Thread-ID erfasse und vergleiche).

Aufgrund von Compiler-Optimierungen erhält der andere Thread dann nie den richtigen Wert. Er erhält einen "veralteten" Wert.

Normalerweise würde ich in einer Situation wie dieser ein "volatile"-Schlüsselwort auf die betreffende Variable anwenden, um zu sehen, ob das Problem dadurch behoben wird. Aber in diesem Fall befinden sich die Variablen innerhalb des MemoryStream-Objekts.

Hat jemand eine andere Idee? Oder bedeutet dies, dass wir unser eigenes MemoryStream-Objekt implementieren müssen?

Mit freundlichen Grüßen, Wayne

EDIT: Ich habe gerade einen Test durchgeführt, der die Gesamtzahl der Aufrufe dieser Methode zählt und die Anzahl der Male zählt, in denen sich die ManagedThreadId vom letzten Aufruf unterscheidet. Es ist fast genau 50% der Zeit, dass es schaltet Threads - abwechselnd zwischen ihnen. Meine obige Theorie ist also mit ziemlicher Sicherheit falsch, sonst würde der Fehler viel häufiger auftreten.

EDIT: T

EDIT: Sperren wird derzeit über lock()-Anweisungen in jeder der 5 Methoden, die den MemoryStream verwenden, behandelt.

7voto

Richard Punkte 103159

(Ich brauche wirklich einen Beispielcode, um das zu bestätigen).

MemoryStream Mitglieder sind nicht als threadsicher dokumentiert (z.B. Position ), so dass Sie sicherstellen müssen, dass Sie nur auf diese Instanz zugreifen (oder auf jeden Verweis auf ein Objekt, das logischerweise ein Teil der MemoryStream ) von einem Thread zum anderen.

Mais MemoryStream es pas als thread-affin dokumentiert, so dass Sie auf eine Instanz von einem anderen Thread aus zugreifen können - solange ein solcher Zugriff nicht gleichzeitig erfolgt.

Gewindeschneiden ist schwierig (für diese Frage und Antwort ist es selbstverständlich).

Ich würde vermuten, dass Sie einige gleichzeitigen Zugriff gehen, mit zwei Threads, die beide gleichzeitig auf die gleiche Instanz zugreifen, und dies ist, gelegentlich, einige Aspekte des Instanzstatus beschädigen.

Ich würde sicherstellen, dass ich das Sperren so einfach wie möglich halte (der Versuch, besonders clever zu sein und das Sperren einzuschränken, ist oft eine Ursache für sehr schwer zu findende Fehler) und die Dinge zum Laufen bringe. Das Testen auf einem Multi-Core-System kann ebenfalls hilfreich sein. Versuchen Sie nur dann, das Sperren zu optimieren, wenn die Profilerstellung zeigt, dass ein erheblicher Nettogewinn (für die Anwendung als Ganzes) möglich ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X