#wpf #performance #idisposable #imagesource #memory-profiling
#wpf #Производительность #idisposable #источник изображения #профилирование памяти
Вопрос:
Я использую его StreamResourceInfo.Stream
для получения BitmapImage
данных из ресурсов. Правильно ли это для Close
и Dispose
потока после его использования? Я спрашиваю, потому что в профилировщике памяти я получаю сообщение об ошибке, если я это делаю. Профилировщик памяти сообщает, что удаленный экземпляр не был GCed.
Если я посмотрю в Интернете, я смогу найти только это сообщение по этой теме. В этом сообщении отвечающий человек говорит, что утилизировать бесполезно. Однако, если я посмотрю на обстоятельства и на эффект, я не думаю, что это правильно. Кто-нибудь знает, какое действие является правильным?
Дополнительная информация: В примерах msdn, которые я видел, они не удаляются и не закрываются.
Редактировать
Благодаря ответу Рика Сладкейса я нашел решение: я присваиваю StreamResourceInfo.Stream
StreamSource
-свойству BitmapImage
. В msdn написано:
Установите для свойства CacheOption значение BitmapCacheOption.Загрузите, если вы хотите закрыть поток после создания растрового изображения. Опция кэша OnDemand по умолчанию сохраняет доступ к потоку до тех пор, пока не потребуется растровое изображение, а очистка не будет выполнена сборщиком мусора.
Это означает, BitmapImage
что он становится владельцем потока. И вот почему профилировщик памяти показывает ошибку, если я закрываю / удаляю поток вручную: Bitmap будет содержать ссылку на поток (BitmapCacheOption OnDemand), и, следовательно, GC не выпустит его, пока BitmapImage действителен, но поток уже явно удален. В этом конкретном примере удаление — плохая идея.
Для полноты я также посмотрел в msdn пример приведенной выше ссылки, где TextRange.Load
был вызван. Для Load
это наоборот, Load
не принимает права собственности, и поэтому поток должен быть закрыт / удален после завершения.
Комментарии:
1.
Dispose
при внутренних вызовах streamsClose
. (Или на самом деле обычно наоборот)2. @Albin: Да, я в курсе этого. AFAIK здесь Close вызывает Dispose . Но вопрос не в этом. Вопрос в том, желательно ли вообще закрывать / утилизировать конкретный поток. В msdn-examples они этого не делают, и если я посмотрю на результат, я сомневаюсь, что это предшествовало / ожидалось. Но в любом случае спасибо.
Ответ №1:
Путаница, и я согласен, что она сбивает с толку, возникает из-за тонкой, но важной концепции владения потоком. В примерах MSDN вы можете смотреть на них так: «Послушайте, нет Dispose
, нет Close
, то есть я не должен этого делать?»
Но простой ответ заключается в том, что кто-то должен нести ответственность за закрытие потока. API, который вы, вероятно, вызываете:
Application.GetResourceStream
возвращает StreamResourceInfo
, который является примитивным контейнером для потока и URL. Очевидно, что StreamResourceInfo
не владеет потоком. Таким образом, при вызове Application.GetResourceStream
вы теперь являетесь владельцем потока, который содержится в этом StreamResourceInfo
, и, если бы вы больше ничего с ним не делали, вы были бы ответственны за его закрытие. Application
API передал нам право собственности на поток от самого себя, вернув его нам в качестве значения.
Теперь возникает запутанная часть, когда вы передаете поток другому объекту. Давайте рассмотрим пример MSDN:
// Navigate to xaml page
Uri uri = new Uri("/PageResourceFile.xaml", UriKind.Relative);
StreamResourceInfo info = Application.GetResourceStream(uri);
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
Page page = (Page)reader.LoadAsync(info.Stream);
this.pageFrame.Content = page;
Теперь в этом примере нет Dispose
и нет Close
. Но происходит передача права собственности на поток от нас (вызывающей стороны) к XamlReader
экземпляру. Поток больше не является нашей ответственностью; мы передали право собственности кому-то другому. На самом деле, XamlReader
вызывает Close
, когда это делается с потоком. Одна загадка решена.
Причина, по которой это так проблематично, заключается в том, что концепция владения обычно подразумевается в документации, и мы должны «просто разобраться в этом». Надеюсь, что просто пересмотр концепции владения и того факта, что оно может передаваться, облегчит вам чувствовать себя комфортно, не вызывая Close
с безопасностью, которая будет у нового владельца. И даже если они этого не сделают, это больше не наша проблема!