C# – How to clear memory stream

cdata-conversionimagememorystreamwcf

I use this code to covert image from binary to image.

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();
    }
}

I had error when loading more than 20 image from my database.
It is Exception was unhandled. The request is not supported.
I think is memory stream full already. So how can I reset the memory stream? I know can be using dispose() or memorystream.setLength to 0 but how to or where should I put the coding?

The exception detail

System.OutOfMemoryException was unhandled
  Message=OutOfMemoryException
  StackTrace:
       at MS.Internal.FrameworkCallbacks.NotifyManagedDebuggerOnNativeOOM()
       at MS.Internal.XcpImports.BitmapSource_SetSourceNative(IntPtr bitmapSource, CValue& byteStream)
       at MS.Internal.XcpImports.BitmapSource_SetSource(BitmapSource bitmapSource, CValue& byteStream)
       at System.Windows.Media.Imaging.BitmapSource.SetSourceInternal(Stream streamSource)
       at System.Windows.Media.Imaging.BitmapImage.SetSourceInternal(Stream streamSource)
       at System.Windows.Media.Imaging.BitmapSource.SetSource(Stream streamSource)
       at MeetPoint_B2C.ImageConverter.Convert(Object value, Type targetType, Object parameter, CultureInfo culture)
       at System.Windows.Data.BindingExpression.ConvertToTarget(Object value)
       at System.Windows.Data.BindingExpression.GetValue(DependencyObject d, DependencyProperty dp)
       at System.Windows.DependencyObject.EvaluateExpression(DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry)
       at System.Windows.DependencyObject.EvaluateBaseValue(DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, ValueOperation operation)
       at System.Windows.DependencyObject.EvaluateEffectiveValue(DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry newEntry, ValueOperation operation)
       at System.Windows.DependencyObject.UpdateEffectiveValue(DependencyProperty property, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, ValueOperation operation)
       at System.Windows.DependencyObject.RefreshExpression(DependencyProperty dp)
       at System.Windows.Data.BindingExpression.RefreshExpression()
       at System.Windows.Data.BindingExpression.SendDataToTarget()
       at System.Windows.Data.BindingExpression.SourceAcquired()
       at System.Windows.Data.BindingExpression.System.Windows.IDataContextChangedListener.OnDataContextChanged(Object sender, DataContextChangedEventArgs e)
       at System.Windows.Data.BindingExpression.DataContextChanged(Object sender, DataContextChangedEventArgs e)
       at System.Windows.FrameworkElement.OnDataContextChanged(DataContextChangedEventArgs e)
       at System.Windows.FrameworkElement.OnAncestorDataContextChanged(DataContextChangedEventArgs e)
       at System.Windows.FrameworkElement.NotifyDataContextChanged(DataContextChangedEventArgs e)
       at System.Windows.FrameworkElement.OnAncestorDataContextChanged(DataContextChangedEventArgs e)
       at System.Windows.FrameworkElement.NotifyDataContextChanged(DataContextChangedEventArgs e)
       at System.Windows.FrameworkElement.OnTreeParentUpdated(DependencyObject newParent, Boolean bIsNewParentAlive)
       at System.Windows.DependencyObject.UpdateTreeParent(IManagedPeer oldParent, IManagedPeer newParent, Boolean bIsNewParentAlive, Boolean keepReferenceToParent)
       at MS.Internal.FrameworkCallbacks.ManagedPeerTreeUpdate(IntPtr oldParentElement, IntPtr parentElement, IntPtr childElement, Byte bIsParentAlive, Byte bKeepReferenceToParent, Byte bCanCreateParent)
       at MS.Internal.XcpImports.Measure_WithDesiredSizeNative(IntPtr element, Single inWidth, Single inHeight, Single& outWidth, Single& outHeight)
       at MS.Internal.XcpImports.UIElement_Measure_WithDesiredSize(UIElement element, Size availableSize)
       at System.Windows.UIElement.Measure_WithDesiredSize(Size availableSize)
       at System.Windows.Controls.VirtualizingStackPanel.MeasureChild(UIElement child, Size layoutSlotSize)
       at System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(Size constraint)
       at System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget, Double inWidth, Double inHeight, Double& outWidth, Double& outHeight)
       at MS.Internal.XcpImports.MeasureOverrideNative(IntPtr element, Single inWidth, Single inHeight, Single& outWidth, Single& outHeight)
       at MS.Internal.XcpImports.FrameworkElement_MeasureOverride(FrameworkElement element, Size availableSize)
       at System.Windows.FrameworkElement.MeasureOverride(Size availableSize)
       at System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget, Double inWidth, Double inHeight, Double& outWidth, Double& outHeight)

This is used by the following .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}}"/>

Best Answer

Since the BitmapImage object takes ownership of the stream, you won't be able to close (or dispose of) it properly, so I recommend something along the lines of:

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; 
} 

In the calling method, implement your own resource cleanup. BitmapImage does not implement IDisposable, so a using statement can't be used. Microsoft should consider implementing IDisposable when it clearly contains references to unmanaged resources:

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();
    }
}

This will ensure that the original MemoryStream is cleaned up properly even in the case of an exception.