Ist der DataContractSerilaizer-Thread von WCF sicher?

9

Ich habe ein ziemlich großes System von Remoting in WCF konvertiert und alles scheint gut zu laufen, außer dass wir häufig die folgende Ausnahme bekommen: "System.InvalidOperationException: Sammlung wurde geändert; Aufzählungsoperation wird möglicherweise nicht ausgeführt." Ich hatte kein Glück, es aufzuspüren, weil es nur passiert, wenn Hunderte von Anrufen durchgereicht werden, und ich kann nur annehmen, dass es daran liegt, dass ein Objekt modifiziert wird, während es serialisiert wird.

Die Klassen verwenden alle: [DataContract(IsReference=true)] .

Es gab keine ähnlichen Ausnahmen bei der Verwendung von Remoting, also frage ich mich, ob jemand ein ähnliches Problem in WCF hatte oder mir mitteilen kann, dass es wahrscheinlich der Serializer ist - in diesem Fall nehme ich an, dass ich meinen eigenen schreiben muss Serialisierer, um locks durchzuführen, wo nötig (was ein großes Unterfangen ist, das ich lieber vermeiden würde).

Das Folgende ist der Stack-Trace:

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)

    
user1766568 23.10.2012, 03:52
quelle

2 Antworten

4

Tatsächlich kann dieser Fehler leicht mit DataContractSerializer reproduziert werden. Es bezieht sich nicht auf Thread-Sicherheit von DataContractSerializer , es handelt sich um Thread-Sicherheit einiger Sammlung, die in Ihren Datenverträgen verwendet wird:

%Vor%

Nach kurzer Ausführungszeit erhalten Sie den IOE mit ähnlicher Stack-Trace:

%Vor%

Sieht so aus, als würden Sie weiterhin einige gemeinsam genutzte Daten ändern, die gleichzeitig serialisiert werden. Sie können die WCF-Ablaufverfolgung aktivieren (siehe diese Frage), um herauszufinden, welche Operation ausgeführt wird verursacht diesen Fehler und schaut genau hin, welche Daten von dieser Operation verwendet werden.

Dann abhängig von den Werten von InstanceContextMode und ConcurrencyMode Eigenschaften des aktuellen Dienstverhaltens, Sie können auswählen, welchen Weg Sie gehen möchten:

  • entweder um eine Sperre zu verwenden;
  • oder um eine threadsichere Sammlung zu verwenden;
  • oder um das Serviceverhalten zu ändern;
  • oder um den Dienst selbst zu ändern (z. B. statuslos machen).
Dennis 23.10.2012, 05:37
quelle
1

Wenn Dennis 'Hypothese richtig ist, dann ist der sauberste Weg, dies zu lösen, das Kopieren der Sammlung und das Versenden der Kopie über die Leitung. An dieser Stelle ist es egal, ob das Original während der Serialisierung geändert wird.

    
Richard Blewett 23.10.2012 07:56
quelle