Suppose I’m accessing a DataTable from multiple threads. If I want to access a particular row, I suspect I need to lock that operation (I could be mistaken about this, but at least I know this way I’m safe):
// this is a strongly-typed table
OrdersRow row = null;
lock (orderTable.Rows.SyncRoot) {
row = orderTable.FindByOrderId(myOrderId);
}
But then, if I want to update that row, should I lock the table (or rather, the table’s Rows.SyncRoot object) again, or can I simply lock the row?
Actually, just performing a
lockin one place on the DataTable or DataRow doesn’t actually do anything. An important aspect to remember in usingMonitorlocks (which is what alockblock is) is that locking an object doesn’t do anything to it; that’s one reason that some advocate using dedicated locking objects rather than locking the resource itself, since it forces you to realize that you have to perform the lock (and on the same object) whenever you’re dealing with the resource.That being said, it’s a better idea to lock the entire
DataTable, as the data storage itself is there (theDataRowobjects internally only contain an offset into theDataTableas to where to retrieve the data). Because of this, even if you synchronize access to individual rows, updating two different rows simultaneously will cause you to update the same data storage mechanism in a non-synchronized manner.There’s a conflict here between viewing internal types as a “black box” and locking only what you need to (which, in this case, would lead you to a faulty conclusion of only locking the row) and trying to gain insight into the internal workings of the type and relying on implementation details that could change.
The upshot is that, right now, you should lock the entire
DataTableto avoid updating the internal data storage system in a non-synchronized manner.