Как очистить поток памяти

Я использую этот код для преобразования изображения из двоичного в изображение.

public class ImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var memStream = new MemoryStream(((MeetPoint_B2C.ServiceReference1.Binary)value).Bytes);
        memStream.Seek(0, SeekOrigin.Begin);
        var empImage = new BitmapImage();
        empImage.CreateOptions = BitmapCreateOptions.None;
        empImage.SetSource(memStream);
        return empImage;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

У меня была ошибка при загрузке более 20 изображений из моей базы данных. Это исключение было необработанным. Запрос не поддерживается. Я думаю, что поток памяти уже заполнен. Так как я могу сбросить поток памяти? Я знаю, можно использовать dispose() или же memorystream.setLength в 0 но как или куда мне поставить кодировку?

Деталь исключения

System.OutOfMemoryException было необработанным. в System.Windows.Media.Imaging.BitmapSource.SetSourceInternal(Stream streamSource) в System.Windows.Media.Imaging.BitmapImage.SetSourceInternal(Stream streamSource) в System.Windows.Media.Imaging.BitmapSource.SetSource(StreamSource) в MeetPoint_B.ImageConverter.Convert(значение объекта, тип targetType, параметр объекта, культура CultureInfo) в System.Windows.Data.BindingExpression.ConvertToTarget (значение объекта) в System.Windows.Data.BindingExpression.GetValue(DependencyObject d, DependencyProperty dp) в системе.Windows.DependencyObject.EvaluateExpression (свойство DependencyProperty, EffectiveValueEntry oldEntry, EffectiveValueEntry & newEn попытаться) в System.Windows.DependencyObject.EvaluateBaseValue(свойство DependencyProperty, EffectiveValueEntry oldEntry, EffectiveValueEntry & newEntry, операция ValueOperation) в System.Windows.DependencyObject.EvaluateEffectiveValue(операция SystemOpenEventEOryEntryEEryEntryEEryEntryEEryEntryEEryEntryEEryEntryEEryEntryEEryEntE бы eEeEntEryEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEeEEEEEEEEEEEeeeE ry)) at at at at at) System System System System at at System).UpdateEffectiveValue(свойство DependencyProperty, EffectiveValueEntry oldEntry, EffectiveValueEntry & newEntry, операция ValueOperation) в System.Windows.DependencyObject.RefreshExpression (DependencyProperty dp) в System.Windows.Data.BindingExpression.Tata.BindingExpression.TataBext.Ref) в System.Windows.Data.BindingExpression.SourceAcquired () в System.Windows.Data.BindingExpression.System.Windows.IDataContextChangedListener.OnDataContextChanged (объект-отправитель, DataContextChangedEventArgs e) в System.Windows.Data.Bedtexth DataContextChangedEventArgs е) при System.Windows.FrameworkElement.OnDataContextChanged (DataContextChangedEventArgs е) при System.Windows.FrameworkElement.OnAncestorDataContextChanged (DataContextChangedEventArgs е) при System.Windows.FrameworkElement.NotifyDataContextChanged (DataContextChangedEventArgs е) при System.Windows.FrameworkElement.OnAncestorDataContextChanged (DataContextChangedEventArgs е) при System.Windows.FrameworkElement.NotifyDataContextChanged (DataContextChangedEventArgs е) при System.Windows.FrameworkElement.OnTreeParentUpdated (DependencyObject newParent, булева bIsNewParentAlive) в System.Windows.DependencyObject.UpdateTreeParent (IManagedPeer oldParent, IManagedPeer newParent, Boolean, Boolean bIsNewParentAlive keepReferenceToParent) в MS.Internal.FrameworkCallbacks.ManagedPeerTreeUpdate (IntPtr oldParentElement, IntPtr parentElement, IntPtr childElement, Байт bIsParentAlive, Байт bKeepReferenceToParent, Байт bCanCreateParent) в MS.Inp. SizeNative(элемент IntPtr, Single inWidth, Single inHeight, Single& outWidth, Single& outHeight) в MS.Internal.XcpImports.UIElement_Measure_WithDesiredSize(элемент UIElement, Size availableSize) в System.Windows.UIElement.Measure_WithDesiredSizeSizeSizeSizeCase (.VirtualizingStackPanel.MeasureChild(дочерний элемент UIElement, Size layoutSlotSize) в System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(ограничение размера) в System.Windows.FrameworkElement.MeasureOverride(IntPtr, двойная ширина, двойная ширина, двойная ширина, двойная ширина, двойная сложность, двойная сложность, двойная сложность, двойная сложность, двойная дробь, двойная сложность, двойная дробь MS.Internal.XcpImports.MeasureOverrideNative(элемент IntPtr, Single inWidth, Single inHeight, Single& outWidth, Single& outHeight) в MS.Internal.XcpImports.FrameworkElement_MeasureOverride(элемент FrameworkElement, доступный размер, размер) (SystemMeESerment) в SystemMWasure.Fase. в System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget, Double inWidth, Double i nHeight, Double & outWidth, Double & outHeight)

Это используется следующими .xaml

<Grid.Resources>
   <src:ImageConverter x:Key="imgConverter"/>
</Grid.Resources>
<Image Grid.Column="1" Grid.Row="4" Height="136" HorizontalAlignment="Left"
    Margin="16,16,0,0" Name="imgEmp" Stretch="Fill"
    VerticalAlignment="Top" Width="200"
    Source="{Binding Image, Converter={StaticResource imgConverter}}"/>

2 ответа

Решение

Так как BitmapImage Объект становится владельцем потока, вы не сможете его закрыть (или утилизировать) должным образом, поэтому я рекомендую что-то вроде:

public BitmapImage Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
{ 
    var empImage = new BitmapImage(); 
    empImage.CreateOptions = BitmapCreateOptions.None; 
    empImage.SetSource(new MemoryStream(((MeetPoint_B2C.ServiceReference1.Binary)value).Bytes); ); 
    return empImage; 
} 

В вызывающем методе реализуйте свою собственную очистку ресурса. BitmapImage не реализует IDisposable, поэтому оператор using не может быть использован. Microsoft должна рассмотреть возможность реализации IDisposable, когда она явно содержит ссылки на неуправляемые ресурсы:

public void ConvertBitmap()
{
    BitmapImage img = null;
    try
    {
        img = Convert(// pass in your params);

        // do stuff with your img
    }
    finally
    {
        // dispose of the memorystream in case of exception
        if(img != null && img.StreamSource != null) img.StreamSource.Dispose();
    }
}

Это гарантирует, что оригинал MemoryStream очищается должным образом даже в случае исключения.

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

Вы должны действительно выяснить, какое именно исключение выдается - это может не иметь ничего общего с нехваткой памяти. Вы отредактировали вопрос, чтобы показать трассировку стека, но не тип создаваемого исключения. Одна из возможностей заключается в том, что это связано с использованием элементов управления WPF в службе WCF, если вам нужны какие-либо теги вопросов.

РЕДАКТИРОВАТЬ: Обратите внимание, что, даже если вы не хотите распоряжаться MemoryStream, вы должны убедиться, что вы избавляетесь от BitmapImage результат, когда вы закончите с этим. К сожалению, у нас недостаточно контекста о том, что вы делаете, чтобы давать какие-либо советы на этот счет.

Другие вопросы по тегам