2009-12-28 3 views
2

У меня есть различные классы, которые обертывают . Они не хранят свои собственные данные (кроме указателя), но вместо этого используют свойства и методы для отображения данных по указателю с использованием неуправляемой библиотеки. Он работает хорошо, но я дошел до того, что мне нужно иметь возможность ссылаться на эти объекты-обертки из других объектов-оберток. Например:Как я могу избежать создания новых объектов-оберток повсюду?

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) (как указано выше), но есть потенциал, имеющий десятки тысяч узлов. Разве это не будет плохой идеей, поскольку несколько объектов-оберток могут в конечном итоге ссылаться на тот же ?

Что можно сделать, чтобы исправить это? Я подумал об использовании статического класса KeyedCollection, который использует каждый ключ . Поэтому, вместо того, чтобы возвращать новый Node каждый раз, я могу просто посмотреть его. Но это вызовет проблемы с резьбой, верно?

Есть ли лучший способ?

ответ

1

Самая большая проблема, которую я вижу, - кто несет ответственность за удаление объектов, на которые указывает указатель?

Повторное использование одного и того же объекта не обязательно является проблемой с потоками, хотя, если вы несете ответственность за вызов delete на неуправляемых объектах, вам необходимо реализовать какой-то подсчет ссылок в ваших объектах.

Использование нескольких объектов с одним и тем же указателем может быть проще, если ваши объекты доступны только для чтения. Если у них есть состояние, которое можно изменить, вам нужно понять влияние внесения изменений, если несколько объектов содержат указатель на это состояние.

Возможно, вы также захотите посмотреть на C++/CLI (управляемый C++), чтобы обеспечить слой между C# и неуправляемой библиотекой и выполнить сложную работу по переводу/манипуляции там и предоставить более простой API для C# для работы с ,

+0

Неуправляемая библиотека обрабатывает состояние. Мои классы просто придают ему представление. Однако я вижу, что вы говорите об удалении объектов. Они одноразовые, но потом я понял, что если они хранятся в «KeyValuePair», объекты все равно не будут собирать мусор. Меня беспокоит накладные расходы, связанные с тем, что тысячи объектов все делают в основном одно и то же. Было бы даже это заметно, или я просто пытаюсь оптимизировать ради оптимизации? C++/CLI не является вариантом, потому что я хочу позже переносить это в Mono. –

+0

В целом создание тысяч объектов приведет к тому, что ваш сборщик мусора начнет головные боли. Другим вариантом может быть передача указателей и наличие вспомогательного класса, который принимает указатель и может возвращать требуемые данные. например Helper.GetIdFromUnmanagedObject (myPtr), а не оболочку указателя в объекте со своим поведением. Не так красиво в терминах OO, но по крайней мере у вас есть только неуправляемые объекты, а не обертки. – Paolo

+0

Да, в основном у меня это уже (неуправляемый API построен в первую очередь так, как в первую очередь), но я действительно пытаюсь подключить его к фреймворку с помощью счетчиков и таким образом сделать его максимально интуитивным. Думаю, я просто подожду и посмотрю, как это получится, и решите статическую коллекцию ссылок, когда это действительно станет проблемой. Я посмотрел на него немного ближе, и вполне возможно, что объекты получат GC'd быстро, так как у них действительно нет ссылок на другие объекты (так как «IntPtrs» - это то, что фактически связывает их вместе). –

0

У меня была связанная с этим проблема. Удаление неуправляемых объектов было выполнено явно. Итак, я сделал базовый класс для всех оболочек, содержащих статический словарь для доступных экземпляров оберток. Объекты были добавлены в словарь в конструкторе и удалены в WrapperBase.Delete(). Обратите внимание, что для такого подхода важно иметь явный метод Delete(), иначе GC никогда не будет освобождать экземпляры оболочек из-за ссылок со статического словаря.

+0

У меня есть IDisposable, реализованный на данный момент, поэтому я всегда мог удалить объект из словаря, когда он был установлен. Проблема в том, что он полностью остался до пользователя. Если объект хранится в словаре, он не получит GC'd. Мне бы не хотелось, чтобы пользователь вызывал Dispose() или Delete() на десятки тысяч объектов. :( –

1

Весь этот код выглядит неправильно.

Ваше использование функции GetParent означает, что у вас есть древовидная структура. Позвольте мне сделать несколько догадок о вашем коде, они могут ошибаться.

  1. Вы хотите широко использовать UnmanagedAPI и не хотите дублировать этот код в коде .NET.

  2. Вы просто хотите удостовериться, что у вас нет проблем с памятью, обратившись к вашему неуправляемому коду.

Я хотел бы предложить, что вместо создания кода .NET на основе узла по узлу, вы создаете .NET обертка для всего дерева/структуры графа и обеспечивают .NET API, который может передавать неуправляемый API указатели в качестве аргументов, но строго контролирует распределение/освобождение, чтобы избежать проблем с памятью.Это позволит избежать ненужного выделения новой структуры памяти просто для выделения того, что уже существует, т. Е. Функции GetParent.

Смежные вопросы