是WCF的DataContractSerilaizer线程安全的? [英] Is WCF's DataContractSerilaizer thread safe?

查看:195
本文介绍了是WCF的DataContractSerilaizer线程安全的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经将一个相当大的系统,从远程到WCF和一切似乎都运行良好,除了我们经常出现以下情况例外:System.InvalidOperationException:集合已修改;枚举操作可能无法执行。我没有任何运气跟踪它了,因为它只有当有上百个电话,通过获得通过发生,我只能假设这是因为一个对象被修改,因为它是正在连载。

I've been converting a fairly large system from Remoting to WCF and everything seems to be running well, except we frequently get the following exception: "System.InvalidOperationException: Collection was modified; enumeration operation may not execute." I haven't had any luck tracking it down because it only happens when there are hundreds of calls getting passed through, and I can only assume it's because an object is being modified as it's being serialized.

所有使用这些类: [DataContract(IsReference = TRUE)]

有使用远程处理时,有没有类似的异常,所以我想知道如果任何人有过类似的问题在WCF中,也可以让我知道,它可能是序列化 - 在这种情况下,我认为我必须写我自己串行执行在必要时(这是一个很大的任务我倒是preFER避免)。

There were no similar exceptions when using remoting, so I'm wondering if anyone has had a similar problem in WCF or can let me know that it probably is the serializer -- in which case I assume I have to write my own serializers to perform locks where necessary (which is a big undertaking I'd prefer to avoid).

以下是堆栈跟踪:

WCF错误:在System.Collections.Generic.List1.Enumerator.MoveNextRare()    在WriteArrayOfLineToXml(XmlWriterDelegator,对象,XmlObjectSerializerWriteContext,CollectionDataContract)    在System.Runtime.Serialization.CollectionDataContract.WriteXmlValue(XmlWriterDelegator的XmlWriter,obj对象,XmlObjectSerializerWriteContext上下文)    在System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator的XmlWriter,obj对象,布尔isDeclaredType,布尔writeXsiType,的Int32 declaredTypeID,的RuntimeTypeHandle declaredTypeHandle)    在System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerializeReference(XmlWriterDelegator XMLWriter的,obj对象,布尔isDeclaredType,布尔writeXsiType,的Int32 declaredTypeID,的RuntimeTypeHandle declaredTypeHandle)    在WriteLineGroupToXml(XmlWriterDelegator,对象,XmlObjectSerializerWriteContext,ClassDataContract)    在System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator的XmlWriter,obj对象,XmlObjectSerializerWriteContext上下文)    在System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithoutXsiType(DataContract dataContract,XmlWriterDelegator的XmlWriter,obj对象,的RuntimeTypeHandle declaredTypeHandle)    在System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerialize(XmlWriterDelegator的XmlWriter,obj对象,布尔isDeclaredType,布尔writeXsiType,的Int32 declaredTypeID,的RuntimeTypeHandle declaredTypeHandle)    在System.Runtime.Serialization.XmlObjectSerializerWriteContext.InternalSerializeReference(XmlWriterDelegator XMLWriter的,obj对象,布尔isDeclaredType,布尔writeXsiType,的Int32 declaredTypeID,的RuntimeTypeHandle declaredTypeHandle)    在WriteLineToXml(XmlWriterDelegator,对象,XmlObjectSerializerWriteContext,ClassDataContract)    在System.Runtime.Serialization.ClassDataContract.WriteXmlValue(XmlWriterDelegator的XmlWriter,obj对象,XmlObjectSerializerWriteContext上下文)    在System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeAndVerifyType(DataContract dataContract,XmlWriterDelegator的XmlWriter,obj对象,布尔verifyKnownType,的RuntimeTypeHandle declaredTypeHandle,类型的declaredType)    在System.Runtime.Serialization.XmlObjectSerializerWriteContext.SerializeWithXsiTypeAtTopLevel(DataContract dataContract,XmlWriterDelegator的XmlWriter,obj对象,的RuntimeTypeHandle originalDeclaredTypeHandle,类型graphType)    在System.Runtime.Serialization.DataContractSerializer.InternalWriteObjectContent(XmlWriterDelegator作家,对象图,DataContractResolver dataContractResolver)    在System.Runtime.Serialization.DataContractSerializer.InternalWriteObject(XmlWriterDelegator作家,对象图,DataContractResolver dataContractResolver)    在System.Runtime.Serialization.XmlObjectSerializer.WriteObjectHandleExceptions(XmlWriterDelegator作家,对象图,DataContractResolver dataContractResolver)    在System.Runtime.Serialization.XmlObjectSerializer.WriteObject(的XmlDictionaryWriter作家,对象图)    在System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameterPart(XmlDictionaryWriter作家,PartInfo部分,对象图)    在System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeParameter(XmlDictionaryWriter作家,PartInfo部分,对象图)    在System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.SerializeBody(XmlDictionaryWriter作家,MessageVersion版本,串动,MessageDescription messageDescription,对象的returnValue,对象[]参数,布尔isRequest)    在System.ServiceModel.Dispatcher.OperationFormatter.SerializeBodyContents(的XmlDictionaryWriter作家,MessageVersion版本,对象[]参数,对象的returnValue,布尔isRequest)    在System.ServiceModel.Dispatcher.OperationFormatter.OperationFormatterMessage.OperationFormatterBodyWriter.OnWriteBodyContents(XmlDictionaryWriter作家)    在System.ServiceModel.Channels.BodyWriter.WriteBodyContents(的XmlDictionaryWriter作家)    在System.ServiceModel.Channels.BodyWriterMessage.OnWriteBodyContents(的XmlDictionaryWriter作家)    在System.ServiceModel.Channels.Message.OnWriteMessage(的XmlDictionaryWriter作家)    在System.ServiceModel.Channels.Message.WriteMessage(的XmlDictionaryWriter作家)    在System.ServiceModel.Channels.BufferedMessageWriter.WriteMessage(消息消息,BufferManager bufferManager,的Int32 initialOffset,的Int32 maxSizeQuota)    在System.ServiceModel.Channels.BinaryMessageEn coderFactory.BinaryMessageEn coder.WriteMessage(消息消息的Int32 maxMessageSize,BufferManager bufferManager,的Int32 messageOffset)    在System.ServiceModel.Channels.FramingDuplexSessionChannel.En codeMessage派生(消息消息)    在System.ServiceModel.Channels.FramingDuplexSessionChannel.OnSend(消息的消息,时间跨度超时)    在System.ServiceModel.Channels.OutputChannel.Send(消息的消息,时间跨度超时)    在System.ServiceModel.Dispatcher.DuplexChannelBinder.DuplexRequestContext.OnReply(消息的消息,时间跨度超时)    在System.ServiceModel.Channels.RequestContextBase.Reply(消息的消息,时间跨度超时)    在System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.Reply(MessageRpc&安培; RPC)

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 的安全,这是一些收集的线程安全,在你的数据契约使用:

Indeed, this error can be easily reproduced with DataContractSerializer. It doesn't refer to thread safety of DataContractSerializer, it is about thread safety of some collection, used in your data contracts:

[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();
    }

在执行时间短,你会得到国际雇主组织类似的堆栈跟踪:

After short execution time, you'll get the IOE with similar stack trace:

   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)

看起来像你继续修改某些共享数据,这被序列化的同时。您可以在WCF打开跟踪(见这个问题)来找出哪些操作造成这个错误,仔细一看,该数据正被此操作。

Looks like you're continuing to modify some shared data, which being serialized the same time. You can turn on WCF tracing (see this question) to find out which operation causes this error, and look carefully, which data being used by this operation.

然后,根据的的值<一href="http://msdn.microsoft.com/en-us/library/system.servicemodel.servicebehaviorattribute.instancecontextmode.aspx"相对=nofollow> InstanceContextMode 和<一href="http://msdn.microsoft.com/en-us/library/system.servicemodel.servicebehaviorattribute.concurrencymode.aspx"相对=nofollow> ConcurrencyMode 当前服务行为的属性,你可以选择哪个方向走:

Then, depending on values of InstanceContextMode and ConcurrencyMode properties of current service behavior, you can choose which way to go:

  • 或者使用一些锁;
  • 或使用任何线程安全的集合;
  • 或更改服务的行为;
  • 或更改服务本身(例如,使其无状态的)。

这篇关于是WCF的DataContractSerilaizer线程安全的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆