2012-05-13 7 views
4

Я использую стороннюю библиотеку, которая является оберткой вокруг родной DLL. библиотека содержит тип XImage, XImage имеет некоторые свойства и метод IntPtr Data(). XImage также реализует IDisposable, но я не знаю, правильно ли оно выполнено.Работа с неуправляемыми ресурсами

Я получаю много XImage s из соединения TCP и показываю их как фильм в PictureBox.

Я использовал для преобразования 'XImage' в System.Drawing.Image и просматривать их в PictureBox, но я получил AccessViolationException.

Поэтому я сделал обертку вокруг XImage под названием Frame.

public class Frame : IDisposable 
{ 
    public uint size { get; private set; } 
    private Image image; 
    public XImage XImage { get; set; } 
    public Image Image { get { return image ?? (image = GetBitmap(this.XImage)); } } 
    public DateTime Time { get; set; } 

    public Frame(XImage xImage) 
    { 
    this.XImage = xImage; 
    this.size = XImage.ImageBufferSize(); 
    GC.AddMemoryPressure(size); 
    } 


    public void Dispose() 
    { 
    Dispose(true); 
    GC.SuppressFinalize(this); 
    } 

    ~Frame() 
    { 
    Dispose(false); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
    if (disposing) 
    { 
     try 
     { 
     image.Dispose(); 
     } 
     catch { } 
     finally 
     { 
     image = null; 
     } 
     try 
     { 
     MImage.Dispose(); 
     } 
     catch { } 
     finally { XImage = null; } 
    } 
    GC.RemoveMemoryPressure(size); 
    } 
} 

и обработки ссылок на Frame Я решил AccessViolationException. теперь у меня есть еще одна проблема, когда я запускаю программу из visual studio (F5 - Start Debugging), все в порядке, но когда я запускаю ее из файла .exe или (ctrl + F5 - Start без отладки), использование памяти увеличивается и больше, пока не получу OutOfMemoryException. (Конфигурация Biuld: Release - X86). что мне делать ?

---- EDIT ----

Я обнаружил, что GC.AddMemoryPressure или GC.RemoveMemoryPressure только делает сбор мусора, чтобы работать более часто, и моя проблема в том, что в настоящее время у меня есть небольшие объекты, которые имеют дескриптор большая неуправляемая память, а GC не собирает эти маленькие объекты.

---- EDIT ----
вызова GC.Collect решит проблему во время выполнения, я установить таймер и вызвать GC.Collect периодически, но это делает замораживание приложения в течение короткого периода, так Я не хочу использовать этот подход.

+2

Вы не решили это, вы просто спрятали его, поймав все исключения. Возникновение проблемы позже неизбежно. Погрузите библиотеку, которая дает вам такие проблемы. –

+0

Вы просто глотаете все исключения в свой метод 'Dispose()'. Скорее всего, «XImage» фактически не удался. – angelsl

+0

@HansPassant: Я думаю, что библиотека в порядке. Я устанавливал таймер и вызывал GC.Collect() каждые 30 секунд и решал «OutOfMemoryException», но это не очень хороший подход. почему запуск под отладчиком отличается от работы без отладчика? – HPT

ответ

0

Я обнаружил, что GC имеет ограничения и может не работать слишком хорошо при очень сильном давлении и интенсивном применении в памяти. У меня есть приложение, которое ничего не делает с неуправляемыми ресурсами напрямую, всеми стандартными компонентами .NET и все еще может захлебываться в памяти. Он может использовать ГБ ОЗУ, но не из-за огромных потребностей в памяти, а потому, что большие объекты создаются и уничтожаются относительно быстро и, по-видимому, не слишком часто собираются. Приложение не имеет утечек памяти, поскольку оно освобождается, когда сбор принудительно. Похоже, что GC не всегда может собирать неиспользуемые объекты вовремя, то есть до OutOfMemoryException. Он ждет, чтобы найти лучший момент, но прежде чем он решит, что уже слишком поздно. Когда я периодически заставляю коллекцию, приложение запускается без проблем.

Следует отметить, что OutOfMemoryException не всегда означает, что вы действительно свободны от памяти. Это также может означать, что нет достаточного количества смежных блоков памяти. Это может иметь место, особенно при работе с видео и изображениями. GC может подумать, что по-прежнему много свободного места в памяти, но оно слишком фрагментировано для вашего приложения. Я уверен, что GC учитывает фрагментацию, но возможно, что это не всегда правильно.

Если вы уверены, что библиотека не проблема, мой совет, чтобы поэкспериментировать с методами давления памяти (AddMemoryPressure и RemoveMemoryPressure), чтобы помочь GC делать свое дело вовремя.Он может решить ваши проблемы, так как вы работаете с неуправляемой библиотекой, которая может обрабатывать значительную часть памяти за спиной GC. Альтернативно сделайте так же, как и с GC.Collect. Сбор вручную может быть не идеальным, но я считаю, что есть случаи, когда это оправдано. Конечно, ожидайте, что ручной сбор множества объектов может повлиять на производительность вашего приложения.

EDIT

Если ручной сбор вводит слишком много влияния на производительность, попробуйте использовать перегруженные версии GC.Collect, которые дают вам немного больше контроля.

+0

Я обнаружил, что GC.AddMemoryPressure или GC.RemoveMemoryPressure просто заставляет сборку мусора работать чаще, и теперь моя проблема заключается в том, что у меня есть небольшие объекты, у которых есть дескриптор большой неуправляемой памяти, а GC не собирает эти маленькие объекты. – HPT

+0

Вы не должны получать OOM, если у вас есть объекты, которые могут быть освобождены. Но, возможно, они по-прежнему ссылаются где-то, например, на очередь завершения. Кроме того, это, похоже, не имеет отношения к этому. – svick

+0

Я бы точно подумал: объекты в ожидании коллекции (даже в очереди финализации) не должны приводить к OOM. К сожалению, это иногда случается на практике. –

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