Требуется ли здесь GC.KeepAlive или я могу полагаться на локальные объекты и аргументы, поддерживающие поддержание объекта? - PullRequest
11 голосов
/ 03 января 2012

У меня есть куча методов, которые берут WPF WriteableBitmap и читают его BackBuffer напрямую, используя небезопасный код.

Не совсем ясно, должен ли я использовать GC.KeepAlive всякий раз, когда я что-то делаюкак это:

int MyMethod(WriteableBitmap bmp)
{
    return DoUnsafeWork(bmp.BackBuffer);
}

С одной стороны, в стеке MyMethod остается ссылка на bmp.С другой стороны, похоже, что мы полагаемся на детали реализации - это может компилироваться в хвостовой вызов, например, без сохранения ссылки bmp в момент ввода DoUnsafeWork.

Аналогично представьте следующую гипотетическуюcode:

int MyMethod()
{
    WriteableBitmap bmp1 = getABitmap();
    var ptr = bmp.BackBuffer;
    WriteableBitmap bmp2 = getABitmap();
    return DoUnsafeWork(ptr, bmp2);
}

Теоретически ссылка на bmp1 остается в стеке до тех пор, пока метод не вернется, но, опять же, похоже, что используется деталь реализации.Конечно, компилятор может объединить bmp1 и bmp2, потому что они никогда не живут в одно и то же время, и даже если компилятор никогда этого не делает, JITter, безусловно, может, и, вероятно, делает (например, сохраняя их оба втот же регистр, сначала один, потом другой).

Итак, в общем: должен ли я полагаться на локальные / аргументы, являющиеся допустимыми ссылками на объект, или мне всегда следует использовать GC.KeepAlive, чтобы гарантировать корректность?

Это особенно озадачивает, поскольку, по-видимому, FxCop считает, что GC.KeepAlive всегда плохой .

Ответы [ 2 ]

12 голосов
/ 03 января 2012

Стоит ли полагаться на то, что локальные / аргументы являются действительными ссылками на объект?

Нет.Ваш анализ верен;джиттер полностью вправе сообщить сборщику мусора, что локальное содержимое перестает работать в тот момент, когда оно больше не используется управляемым кодом.правильность?

Да.Вот для чего это.

0 голосов
/ 03 января 2012

Если вы вызвали WriteableBitmap.Lock перед получением обратного буфера, тогда WriteableBitmap должен быть закреплен, а основная память не будет перемещена.По крайней мере, это моя интерпретация WriteableBitmapAPI.

Я широко использовал WriteableBitmap, в частности библиотеку WriteableBitmapEx с открытым исходным кодом на codeplex (раскрытие, я однажды внес вклад в эту библиотеку, но это не мой проект).При этом для рисования используется шаблон блокировки / доступа к буферу (многократно) / разблокировки / аннулирования.У меня никогда не было проблем с этим шаблоном, несмотря на то, что BackPuffer IntPtr хранится в структуре и передается приложению.

С уважением,

...