use*_*568 9 .net c# wcf multithreading thread-safety
我一直在将一个相当大的系统从Remoting转换为WCF,一切似乎运行良好,除了我们经常得到以下异常:"System.InvalidOperationException:Collection被修改;枚举操作可能无法执行." 我没有任何运气跟踪它,因为它只发生在有数百个调用通过时,我只能假设它是因为一个对象被修改,因为它被序列化.
所有类都使用:[DataContract(IsReference=true)].
在使用远程处理时没有类似的例外,所以我想知道是否有人在WCF中遇到过类似的问题,或者可以让我知道它可能是序列化程序 - 在这种情况下我假设我必须编写自己的序列化程序来执行locks必要时(这是一项我宁愿避免的大事).
以下是堆栈跟踪:
WCF Error: at System.Collections.Generic.List1.Enumerator.MoveNextRare()
at WriteArrayOfLineToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , CollectionDataContract )
at System.Runtime.Serialization.CollectionDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerializeReference(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
at WriteLineGroupToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , ClassDataContract )
at System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerializeReference(XmlWriterDelegator xmlWriter, Object obj, Boolean isDeclaredType, Boolean writeXsiType, Int32 declaredTypeID, RuntimeTypeHandle declaredTypeHandle)
at WriteLineToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , ClassDataContract )
at System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, Boolean verifyKnownType, RuntimeTypeHandle declaredTypeHandle, Type declaredType)
at System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiTypeAtTopLevel(DataContract dataContract, XmlWriterDelegator xmlWriter, Object obj, RuntimeTypeHandle originalDeclaredTypeHandle, Type graphType)
at System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator writer, Object graph, DataContractResolver dataContractResolver)
at System.Runtime.Serialization.XmlObjectSerializer.WriteObject(XmlDictionaryWriter writer, Object graph)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameterPart(XmlDictionaryWriter writer, PartInfo part, Object graph)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameter(XmlDictionaryWriter writer, PartInfo part, Object graph)
at System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter writer, MessageVersion version, String action, MessageDescription messageDescription, Object returnValue, Object[] parameters, Boolean isRequest)
at System.ServiceModel.Dispatcher.OperationFormatter.SerializeBodyContents(XmlDictionaryWriter writer, MessageVersion version, Object[] parameters, Object returnValue, Boolean isRequest)
at System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage.OperationFormatterBodyWriter.OnWriteBodyContents(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.BodyWriter.WriteBodyContents(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.BodyWriterMessage.OnWriteBodyContents(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.Message.WriteMessage(XmlDictionaryWriter writer)
at System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(Message message, BufferManager bufferManager, Int32 initialOffset, Int32 maxSizeQuota)
at System.ServiceModel.Channels.BinaryMessageEncoderFactory.BinaryMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset)
at System.ServiceModel.Channels.FramingDuplexSessionChannel.EncodeMessage(Message message)
at System.ServiceModel.Channels.FramingDuplexSessionChannel.OnSend(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.OutputChannel.Send(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.DuplexChannelBinder.DuplexRequestContext.OnReply(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.RequestContextBase.Reply(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Reply(MessageRpc& rpc)
实际上,这个错误可以很容易地再现DataContractSerializer.它不涉及线程安全性DataContractSerializer,它是关于某些集合的线程安全性,用于您的数据协定:
[DataContract]
public class C
{
[DataMember]
public List<int> Values { get; set; }
}
class Program
{
static void Main(string[] args)
{
var c = new C
{
Values = new List<int>()
};
var serializer = new DataContractSerializer(typeof(C));
Task
.Factory
.StartNew(() =>
{
while (true)
{
Console.WriteLine("Trying to add new item.");
c.Values.Add(DateTime.Now.Millisecond);
}
},
TaskCreationOptions.LongRunning);
Task
.Factory
.StartNew(() =>
{
while (true)
{
using (var stream = new MemoryStream())
{
Console.WriteLine("Trying to serialize.");
serializer.WriteObject(stream, c);
}
}
},
TaskCreationOptions.LongRunning);
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
在短暂的执行时间之后,您将获得具有类似堆栈跟踪的IOE:
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource) at System.Collections.Generic.List`1.Enumerator.MoveNextRare() at System.Collections.Generic.List`1.Enumerator.MoveNext() at WriteArrayOfintToXml(XmlWriterDelegator , Object , XmlObjectSerializerWriteContext , CollectionDataContract ) at System.Runtime.Serialization.CollectionDataContract.WriteXmlValue(XmlWriterDelegator xmlWriter, Object obj, XmlObjectSerializerWriteContext context)
Run Code Online (Sandbox Code Playgroud)
看起来你正在继续修改一些同时被序列化的共享数据.您可以打开WCF跟踪(请参阅此问题)以找出导致此错误的操作,并仔细查看此操作使用的数据.
然后,根据当前服务行为的InstanceContextMode和ConcurrencyMode属性的值,您可以选择要采用的方法:
| 归档时间: |
|
| 查看次数: |
1331 次 |
| 最近记录: |