.net C# DataTable序列化多线程问题

最近在项目中遇到一个bug,调了好久,也查了好久,今天终于搞定了!

在 System.Data.DataTable.SerializeDataTable(SerializationInfo info, StreamingContext context, Boolean isSingleTable, SerializationFormat remotingFormat)
   在 System.Data.DataTable.GetObjectData(SerializationInfo info, StreamingContext context)
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
   在 System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
   在 System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
   在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
   在 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
   在 BitAuto.AutoCommune.CacheManager.CacheContext.WriteDataToDisk[T](String businessDic, String cacheKeyDic, String strkey, T data)

 以上是异常信息。。。

最后结果是,.netFramwork 的一个bug。DataTable不支持多线程序列化 。

在对DataTable进行序列化时,需要这个DataTable依附在一个DataSet上面,如果DataTable.DataSet为空,则会创建 一个临时的DataSet对象并把需要序列化的DataTable加到DataSet上面,等序列化好了,再把DataSet移掉(不知道微软为什么要这 么设计)。

问题就来了,如果有多个线程在对同一个DataTable进行序列化时,就有可能会出现线程间的同步化问题。原因是在对DataSet.Tables集合进行增加、移除时,没有考虑到多线程问题,从而可能导致上文异常。
 
为了解决这个问题,一个变通的方法是给需要序列化的DataTable显示地指定一个DataSet,这样序列化时就不需要创建临时的DataSet,可不会有多线程的问题了。
DataSet myDS = new DataSet("MyDataSet");
myDS.Tables.Add(myTable);    // myTable即是要序列化的DataTable对象。

本人总结:在msdn上看到这句话:DataSet类

该类型对于多线程读操作是安全的。您必须使任何写操作同步。

意思是DataSet类的读操作是线程安全的,但是写操作是不安全的。此Bug中如果给每个DataTable指定一个DataSet的话,.net就不会为每一个DataTable指定临时DataSet,而恰恰这样会出现DataSet的增加、修改等写操作(线程不安全的)!为每一个DataTable指定自己DataSet就只有读操作(线程安全的)!

所以也不能说是。netFramework的bug,因为DataTable和DataSet都是读操作线程安全的。而此时。net序列化DataTable时又需要临时DataSet支持,造成此问题出现,是我们不太了解。net的内部机制,误用而已!

原文地址:

http://blog.163.com/yinson_lin/blog/static/2212017201002935926117/

 参考地址:

http://kbalertz.com/903645/exception-occurs-instance-DataSet-typed-object-serialized-multiple-threads-access-instance-DataSet-typed-object-synchronously.aspx

原文地址:https://www.cnblogs.com/zhaoguo435/p/2012290.html