1

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

次のように「Clone」メソッドを持つ「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

したがって、基本的には、選択した Mode オブジェクトの 1 つまたは複数のクローンを作成し、Name プロパティを正しい値に設定し、新しい Mode オブジェクトを親に追加する必要があります。これには、Mode.Clone メソッドへの X 回の呼び出しと、CloneViaSerialization 拡張メソッドへの X 回の呼び出しが含まれます。

これが私の問題です。CloneViaSerialization を複数回呼び出している間、MemoryString の長さ (Debug.WriteLine ステートメントで表示される) は、前回の呼び出しのほぼ 2 倍になります。たとえば、5 つのクローンを作成すると、デバッグ出力は次のようになります。

MS の長さ = 106882 MS の長さ = 188048 MS の長さ = 350482 MS の長さ = 675350 MS の長さ = 1325086

これは致命的なパフォーマンスです。約 7 または 8 個のクローンを超えると、アプリが停止します。なぜこれが起こるのでしょうか?USING ブロックは、MemoryString が確実に破棄されるようにする必要がありますね。毎回新しい MemoryString を作成するべきではありませんか? 同じ元の Mode オブジェクトがシリアル化のソースであるため、MemoryString の長さは同じになると思います。何か案は?ここで何が欠けていますか?

前もって感謝します!

4

1 に答える 1

0

なぜあなたCloneViaSerializationが大量のメモリを消費しているのかわかりませんが、あなたが投稿したコードは私には問題ないようです(ただし、クローンされたデータが大きいという可能性もあります)。別のアプローチはICloneable、クラスに実装し、オブジェクトのディープ コピーを実行するように関数をMode設定することです。Clone

Public Class Mode 
    Implements ICloneable

    Private m_Prop1 As String
    Public Property Prop1() As String
        Get
            Return m_Prop1
        End Get
        Set
            m_Prop1 = Value
        End Set
    End Property

    Private m_Prop2 As Int16
    Public Property Prop2() As Int16
        Get
            Return m_Prop2
        End Get
        Set
            m_Prop2 = Value
        End Set
    End Property

    Private m_Prop3 As List(Of Int16)
    Public Property Prop3() As List(Of Int16)
        Get
            Return m_Prop3
        End Get
        Set
            m_Prop3 = Value
        End Set
    End Property

    Public Function Clone() As Object Implements ICloneable.Clone
        Dim objClone as Mode
        objClone = MemberwiseClone()
        If Not Me.Prop3 Is Nothing Then
            objClone.Prop3 = new List(Of Int16)
            objClone.Prop3.AddRange(Me.Prop3)
        End If
        Return objClone
    End Function

End Class

Clone関数では、 の別のコピーを作成する必要があることに注意してくださいList(Of Int16)MemberwiseClone作成した新しいオブジェクトに参照をコピーするため、新しいオブジェクトを作成せずList(Of Int16)に値を手動でコピーすると、クローンの元のリストへの参照が作成されます。

また、浅いコピーしかできないICloneableため、ディープ コピーの実装と実行に問題を抱えている人もいることを指摘しておく必要があります。MemberwiseCloneそれが気になる場合は、いつでもインターフェイスの名前を変更CloneDeepCloneて削除ICloneableできます。

それが役立つことを願っています。

于 2011-04-26T06:12:30.447 に答える