2010-04-09 6 views
7

Angenommen, ich greife auf eine DataTable von mehreren Threads. Wenn ich eine bestimmte Zeile zugreifen will, vermute ich, ich brauche diesen Betrieb zu sperren (ich kann darüber verwechselt werden, aber zumindest weiß ich auf diese Weise ich sicher bin):Wenn ich eine DataRow aktualisiere, sperre ich die gesamte DataTable oder nur die DataRow?

// this is a strongly-typed table 
OrdersRow row = null; 
lock (orderTable.Rows.SyncRoot) { 
    row = orderTable.FindByOrderId(myOrderId); 
} 

Aber dann, wenn ich will aktualisieren diese Zeile, sollte ich die Tabelle (oder vielmehr, die Tabelle Rows.SyncRoot Objekt) wieder sperren, oder kann ich einfach die Zeile sperren?

Antwort

5

Eigentlich nur einen lock an einem Ort auf der Datatable oder DataRow Durchführung nicht wirklich nichts tun. Ein wichtiger Aspekt bei der Verwendung von Monitor Sperren (was ein lock Block ist) ist, dass das Sperren eines Objekts nichts dagegen tut; Das ist ein Grund, warum einige dafür plädieren, dedizierte Sperrobjekte zu verwenden, anstatt die Ressource selbst zu sperren, da sie zwingt, zu erkennen, dass Sie die Sperre (und für dasselbe Objekt) immer dann ausführen müssen, wenn Sie mit der Ressource zu tun haben.

Davon abgesehen, ist es eine bessere Idee, die gesamte DataTable zu sperren, da der Datenspeicher selbst besteht (die DataRow Objekte intern nur eine in den DataTable Offset enthalten, wo die Daten abzurufen). Aus diesem Grund führt die Aktualisierung von zwei verschiedenen Zeilen gleichzeitig dazu, dass Sie denselben Datenspeichermechanismus auf nicht synchronisierte Weise aktualisieren, selbst wenn Sie den Zugriff auf einzelne Zeilen synchronisieren.

Es besteht ein Konflikt zwischen dem Anzeigen interner Typen als "Black Box" und dem Sperren nur der benötigten Informationen (was in diesem Fall zu einer fehlerhaften Schlussfolgerung führen würde, nur die Zeile zu sperren) und versuchen, Einsicht zu gewinnen in die internen Arbeiten des Typs und unter Berufung auf Implementierungsdetails , die ändern könnte.

Das Ergebnis ist, dass Sie jetzt den gesamten DataTable sperren sollten, um zu vermeiden, das interne Datenspeichersystem in einer nicht synchronisierten Weise zu aktualisieren.

+0

Sehr aufschlussreiche Antwort, und ich kann sehen, warum Sie das Bedürfnis verspürten, darauf hinzuweisen, wie der 'Schloss'-Mechanismus funktioniert ... Ich habe erkannt, dass die Verriegelung nichts zu einem Objekt * macht; Ich denke, eine bessere Art, wie ich meine Frage hätte formulieren können, wäre "Muss ich Update-Operationen pro Zeile oder pro Tabelle synchronisieren?" In jedem Fall ist es für mich an dieser Stelle klar, dass ich Updates auf * any * row über die gesamte Tabelle synchronisieren muss - sei es durch Sperren der Tabelle oder durch eine dedizierte "table lock" (in diesem Fall denke ich, die 'Rows. SyncRoot' Objekt erfüllt diesen Zweck gut, eigentlich). –

3

Sie müssen nicht für Lesevorgänge sperren - nur für Schreibvorgänge/Updates. Sperren Sie die kleinste Menge, die Sie können, um die Datenkonsistenz zu gewährleisten ... in der Regel nur die eine Zeile, die Sie aktualisieren. Wenn Sie Eltern-Kind-Beziehungen zwischen Tabellen aktualisieren, müssen Sie jede Zeile in jeder Tabelle sperren.

+0

Der von Kevin bereitgestellte Link (http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/11b69e1a-ad6c-48d5-8e14-264af5b0692e) scheint anzuzeigen, dass das Sperren der Tabelle ist eigentlich notwendig. Der MSFT-Repräsentant sagt: "Angenommen, das Aktualisieren einer einzelnen Zeile wirkt sich nicht auf andere Tabellen aus, ist gefährlich, da Sie sich auf ein mögliches Implementierungsdetail verlassen, das zu einem späteren Zeitpunkt leicht unterbrochen werden kann." Hast du einen Einblick, ob das wahr ist oder nicht? –

3

Die Datentabelle ist nur sicher für Multi-Threaded-Leseoperationen:

http://msdn.microsoft.com/en-us/library/system.data.datatable.aspx

http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/11b69e1a-ad6c-48d5-8e14-264af5b0692e

On über die Datentabelle zu lesen gibt es widersprüchliche Informationen über die Möglichkeit, die Tabelle zu sperren und ermöglichen es Ihnen sicher Daten nacheinander aktualisieren Gemäß dem zweiten Link können Sie die Tabelle sperren und die Zeile aktualisieren. Da dies von einem MS MVP ist, würde ich sagen, dass Sie die Tabelle wahrscheinlich sperren können und in Ordnung sein.

+1

Der Link lautet: "Dieser Typ ist sicher für Multithread-Lesevorgänge. Sie müssen alle Schreibvorgänge synchronisieren" Bedeutet dies nicht, dass eine Sperre das richtige für Multithread-Zugriff ist? – code4life

+0

Ich bin verwirrt; der erste Link, den Sie zur Verfügung gestellt haben, scheint zu sagen, dass Sie nur Schreibvorgänge sperren müssen (obwohl es nicht sagt, * was * gesperrt werden soll). Die zweite scheint darauf hinzuweisen, dass das Sperren der Tabelle der richtige Ansatz ist. Keine scheint Ihrer Aussage zuzustimmen, dass Sie die Tabelle nicht sperren können und erwarten, dass die Lesevorgänge konsistent sind. Fehle ich etwas? –

+0

Meine erste Aussage war falsch. Ich habe widersprüchliche Informationen gefunden. Sie müssen die Tabelle nicht sperren, um Daten zu lesen, da dies in Ordnung ist. Sie müssen die Tabelle sperren, um Daten zu schreiben. – kemiller2002