[Bearbeiten: Es sieht so aus, als ob die ursprüngliche Frage ein Double und keine Ganzzahl war. Also ich denke, diese Frage steht, wenn wir die ganze Zahl in ein Double ändern.]
Ich habe ein seltenes Problem beim Lesen von Integer-Eigenschaften aus einer Klasse, die in mehreren Threads verwendet wird und manchmal einen Wert von Null zurückgibt. Die Werte werden nach der Initialisierung nicht geändert.
Diese Frage spricht das an. Der Konsens ist, dass obwohl ich auf eine ganze Zahl zugreife, ich die Eigenschaften synchronisieren muss. (Einige der ursprünglichen Antworten wurden gelöscht). Ich habe dort keine Antwort gewählt, weil ich mein Problem noch nicht gelöst habe.
Also habe ich einige Nachforschungen darüber angestellt und bin mir nicht sicher, welche der Sperrmechanismen von .Net 4 verwendet werden sollen oder ob die Sperren außerhalb der Klasse selbst liegen sollten.
Das habe ich mir überlegt:
%Vor%Aber ich habe gelesen, dass das furchtbar langsam ist.
Eine andere Alternative ist, die Instanz von ConfigData
auf der Benutzerseite zu sperren, aber das scheint eine Menge Arbeit zu sein. Eine andere Alternative, die ich gesehen habe, ist Monitor.Enter
und Monitor.Exit
, aber ich denke, Lock ist das Gleiche mit weniger Syntax.
Was ist also eine bewährte Methode zum Erstellen des Eigenschaften-Threads einer Klasse? sicher?
a. Die Verwendung der Sperre kann langsam sein, da Betriebssystemressourcen verwendet werden. Wenn die Komplexität der Eigenschaften gering ist, wird Spin Lock (oder interlocked.compareexchange) schneller.
b. Sie müssen sicherstellen, dass ein Thread nicht in eine Sperre eintritt und über einen Anruf von einer Eigenschaft zur anderen gesperrt wird. - Wenn dies passieren kann (momentan kein Problem in Ihrem Code), müssen Sie den Sperr-Thread oder die Aufgabe sensitiv machen.
Bearbeiten:
Wenn das Objekt während der Initialisierung gesetzt und nie geändert werden soll, machen Sie es unveränderlich (wie .NET-Strings). Entfernen Sie alle öffentlichen Setter und geben Sie einem Konstruktor Parameter zum Definieren des Anfangszustands und möglicherweise zusätzliche Methoden / Operatoren zum Erstellen einer neuen Instanz mit einem modifizierten Status (z. B. var newString="Alte Zeichenfolge" + "wurde geändert.";).
Ich denke, du solltest deine ConfigInfo
-Klasse so umschreiben, dass sie so aussieht; Dann können Sie keine Überlauf- oder Threading-Probleme bekommen:
Beachten Sie, dass ich checked
verwende, um Überlaufprobleme zu erkennen.
Andernfalls geben einige Werte falsche Ergebnisse.
Zum Beispiel gibt 57344 * 524288
in der ungeprüften Ganzzahlarithmetik Null an (und es gibt sehr viele andere Wertepaare, die Null ergeben, und sogar mehr, die ein negatives Ergebnis oder einen positiven Wert ergeben, der "scheint" korrekt zu sein).
Es ist am besten, wie in den Kommentaren erwähnt, die Eigenschaften readonly zu machen. Ich dachte über die folgende Möglichkeit nach:
%Vor%Auf diese Weise stimmt Ihr TimerInterval Wert immer mit seinen Faktoren überein. Das einzige Problem ist, wenn ein Thread eine der Eigenschaften liest, während ein anderer sie von außerhalb der ConfigInfo schreibt. Der erste könnte einen falschen Wert erhalten, und ich sehe keinen Weg, dies zu lösen, ohne einen einzigen Lock-Root einzuführen. Die Frage ist, ob Lesevorgänge kritisch sind.
Tags und Links c# multithreading thread-safety c#-4.0 properties