BinaryFormatter.Serialize 与 MemoryStream 问题
我在使用 BinaryFormatter.Serialize 时遇到问题。
我有一个通用扩展方法来通过二进制序列化“克隆”对象:
<Extension()>
Public Function CloneViaSerialization(ByRef Obj as System.Object)
Dim NewObj As System.Object
Using MS As New System.IO.MemoryStream
Dim Formatter as New BinaryFormatter
Formatter.Serialize(MS, Obj)
Debug.WriteLine("MS LENGTH = " & MS.Length)
MS.Position = 0
NewObj = Formatter.Deserialize(MS)
End Using
Return NewObj
End Function
我还有一个名为“Mode”的类,它有一个“克隆”方法,如下所示:
Friend Function Clone()
Dim NewMode as Mode = Me.CloneViaSerialization
Return NewMode
End Function
在我的 GUI 中,我有一个函数允许选定的 Mode 对象被克隆。用户输入一系列新模式名称,例程会循环使用这些新名称,创建所选模式的克隆:
Private Sub MakeClones(ByRef ModeToClone as Mode, ByVal CloneNames as List(Of String))
For Each CloneName as String in CloneNames
Dim NewMode as Mode = ModeToClone.Clone
NewMode.Name = CloneName
ParentObject.Modes.Add(NewMode)
Next
End Sub
因此,基本上应该创建所选模式对象的一个或多个克隆,将 Name 属性设置为正确的值,并且添加到父对象的新模式对象。这涉及对 Mode.Clone 方法的 X 次调用,以及对 CloneViaSerialization 扩展方法的 X 次调用。
这是我的问题。在多次调用 CloneViaSerialization 期间,MemoryString 长度(如 Debug.WriteLine 语句中显示)几乎是前一次调用的两倍。例如,制作五个克隆,调试输出为:
MS 长度 = 106882 MS 长度 = 188048 MS 长度 = 350482 MS 长度 = 675350 MS 长度 = 1325086
这是令人窒息的性能。超过 7 或 8 个克隆就会导致应用程序停止运行。为什么会出现这种情况呢? USING 块应该确保 MemoryString 被释放,对吧?不应该每次都创建一个新的MemoryString吗?我认为由于相同的原始 Mode 对象是序列化的源,因此 MemoryString 长度将是相同的。有什么想法吗?我在这里缺少什么?
提前致谢!
I am having an issue using BinaryFormatter.Serialize.
I have this generic extension method to "clone" an object via binary serialization:
<Extension()>
Public Function CloneViaSerialization(ByRef Obj as System.Object)
Dim NewObj As System.Object
Using MS As New System.IO.MemoryStream
Dim Formatter as New BinaryFormatter
Formatter.Serialize(MS, Obj)
Debug.WriteLine("MS LENGTH = " & MS.Length)
MS.Position = 0
NewObj = Formatter.Deserialize(MS)
End Using
Return NewObj
End Function
I also have a class called "Mode" which has a method "Clone" as follows:
Friend Function Clone()
Dim NewMode as Mode = Me.CloneViaSerialization
Return NewMode
End Function
Within my GUI, I have a function that allows a selected Mode object to be cloned. The user enters a series of new mode names and the routine cycles through those new names creating clones of the selected mode:
Private Sub MakeClones(ByRef ModeToClone as Mode, ByVal CloneNames as List(Of String))
For Each CloneName as String in CloneNames
Dim NewMode as Mode = ModeToClone.Clone
NewMode.Name = CloneName
ParentObject.Modes.Add(NewMode)
Next
End Sub
So basically one or more clones of the selected Mode object ought to be created, the Name property set to the correct value, and the new Mode objects added to the parent. This involves X number of calls to the Mode.Clone method and in-turn X calls to the CloneViaSerialization extension method.
Here's my issue. During multiple calls of CloneViaSerialization, the MemoryString length (as displayed at the Debug.WriteLine statement) is almost double what is was the previous call. For example, making five clones, the debug output is:
MS LENGTH = 106882
MS LENGTH = 188048
MS LENGTH = 350482
MS LENGTH = 675350
MS LENGTH = 1325086
This is killing performance. Anything more that about 7 or 8 clones brings the app to a halt. Why would this happen? The USING block ought to ensure the MemoryString is disposed of, right? Shouldn't a new MemoryString be created each time? I would think since the same original Mode object is the source for the serialization, the MemoryString length would be the same. Any ideas? What am I missing here?
Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不确定为什么您的 CloneViaSerialization 消耗大量内存,您发布的代码对我来说似乎没问题(尽管一种可能的解释可能是被克隆的数据很大)。另一种方法是仅在
Mode
类上实现ICloneable
并设置Clone
函数来执行对象的深层复制。请注意,在
Clone
函数中,我们需要对List(Of Int16)
进行单独的复制。MemberwiseClone
会将引用复制到它创建的新对象中,因此,如果我们不创建新的List(Of Int16)
并手动复制其中的值,那么我们就会结束并引用克隆中的原始列表。我还应该指出,有些人可能在实现
ICloneable
并让它执行深复制时遇到问题,因为MemberwiseClone
只执行浅复制。如果这让您感到困扰,那么您可以随时将Clone
重命名为DeepClone
并删除ICloneable
接口。希望有帮助。
I'm not sure why your
CloneViaSerialization
is consuming large amounts of memory, the code you posted seems ok to me (although one possible explanation could just be that the data being cloned is large). An alternative approach is to just implementICloneable
on yourMode
class and set up yourClone
function to do a deep copy of your object.Please be aware that in the
Clone
function, we need to do a separate copy of theList(Of Int16)
.MemberwiseClone
will copy references into the new object it creates, so if we don't create a newList(Of Int16)
and manually copy the values in then we'll wind up with a reference to the original list in the clone.I also should point out that some people may have a problem implementing
ICloneable
and having it do a deep copy, sinceMemberwiseClone
only does shallow copies. If that bothers you then you can always renameClone
toDeepClone
and remove theICloneable
interface.Hope that helps.