2

をラップするさまざまなクラスがありIntPtrます。独自のデータ(ポインター以外)を格納しませんが、代わりにプロパティとメソッドを使用して、アンマネージライブラリを使用してポインターでデータを公開します。それはうまく機能しますが、他のラッパーオブジェクトからこれらのラッパーオブジェクトを参照できるようにする必要があるところまで来ました。例えば:

public class Node {
    private IntPtr _ptr;

    public Node Parent {
        get { return new Node(UnmanagedApi.GetParent(_ptr)); }
    }

    internal Node(IntPtr ptr) {
        _ptr = ptr;
    }
}

これで、(上記のように)単純に返すことができますnew Node(parentPtr)が、数万のノードを持つ可能性があります。複数のラッパーオブジェクトが同じものを参照する可能性があるため、これは悪い考えではないでしょうIntPtrか。

これを修正するにはどうすればよいですか?それぞれをキーとして使用する静的KeyedCollectionクラスを使用することを考えました。だから、毎回IntPtr新しいものを返す代わりに、私はそれを調べることができます。Nodeしかし、それはスレッドの問題を引き起こしますよね?

もっと良い方法はありますか?

4

3 に答える 3

1

このコード全体が正しく見えません。

GetParent関数を使用することは、ツリーのような構造を持っていることを意味しているようです。あなたのコードについていくつか推測させてください、それらは間違っている可能性があります。

  1. UnmanagedAPIを多用し、このコードを.NETコードに複製したくない場合。

  2. 損傷を受けていないコードにアクセスして、メモリの問題が発生しないようにするだけです。

ノードごとに.NETコードを作成する代わりに、ツリー/グラフ構造全体の.NETラッパーを作成し、アンマネージAPIポインターを引数として渡すことができるが厳密に処理する.NETAPIを提供することをお勧めします。メモリの問題を回避するための割り当て/割り当て解除。これにより、既存の何か、つまりGetParent関数を割り当てるためだけに、新しいメモリ構造が不要に割り当てられるのを防ぐことができます。

于 2009-12-28T09:21:13.127 に答える
1

私が見ることができる最大の問題は、ポインタによって参照されるオブジェクトを削除する責任があるのは誰かということです。

同じオブジェクトを再利用することは必ずしもスレッドの問題ではありませんが、アンマネージオブジェクトでdeleteを呼び出す必要がある場合は、オブジェクトに何らかの参照カウントを実装する必要があります。

オブジェクトが読み取り専用の場合、同じポインタで複数のオブジェクトを使用する方が簡単な場合があります。変更可能な状態がある場合、複数のオブジェクトがその状態へのポインターを保持している場合に変更を加えることの影響を理解する必要があります。

また、C ++ / CLI(マネージC ++)を調べて、C#とアンマネージライブラリの間にレイヤーを提供し、そこで変換/操作のハードワークを実行し、C#で動作するためのより単純なAPIを提供することもできます。

于 2009-12-28T08:57:55.077 に答える
0

関連する問題がありました。管理されていないオブジェクトの削除は明示的に行われました。したがって、私が行ったことは、使用可能なラッパーインスタンスの静的ディクショナリを含むすべてのラッパーの基本クラスを作成することでした。オブジェクトはコンストラクターでディクショナリに追加され、WrapperBase.Delete()メソッドで削除されました。このようなアプローチには明示的なDelete()メソッドを使用することが重要であることに注意してください。そうしないと、静的ディクショナリからの参照のために、GCがラッパーインスタンスを解放することはありません。

于 2009-12-28T09:02:46.533 に答える