Error when setting "large" data stream as source for BitmapImage

2

I use a cache mechanism, which saves images to the isolated storage and load it the next times, especially when there's no internet connection. However, it works fine for small images, but not for "large" images which are about 200kb.

This is my code:

public static object ExtractFromLocalStorage(Uri imageFileUri, string imageStorageFolder)
{
    var isolatedStoragePath = GetFileNameInIsolatedStorage(imageFileUri, imageStorageFolder);

    MemoryStream dataStream;
    using (var fileStream = Storage.OpenFile(isolatedStoragePath, FileMode.Open, FileAccess.Read))
    {
        if (fileStream.Length > int.MaxValue)
            return null;
        dataStream = new MemoryStream((int)fileStream.Length);
        var buffer = new byte[4096];
        while (dataStream.Length < fileStream.Length)
        {
            var readCount = fileStream.Read(buffer, 0, Math.Min(buffer.Length, (int)(fileStream.Length - dataStream.Length)));
            if (readCount <= 0)
            {
                throw new NotSupportedException();
            }
            dataStream.Write(buffer, 0, readCount);
        }
    }
    var bi = new BitmapImage();
    Deployment.Current.Dispatcher.BeginInvoke(() => bi.SetSource(dataStream));
    return bi;
}

Small images work fine, but I get the following exception when bi.SetSource is being called, when loading such 200kb+ images: The component cannot be found. (Exception from HRESULT: 0x88982F50)

Is there anything I can do about it? 200kb is not too large and the file is saved fine and exists locally. I hope someone can help me since it's the last stopper for my app... :/

EDIT (31 jan):

I started all over again, using the KawagoeToolkit library which I extended by necessary methods for my app. It works well, but I still wonder why the above gives such a strange exception.

c#
exception
windows-phone
bitmapimage
asked on Stack Overflow Jan 27, 2014 by sibbl • edited Jan 31, 2014 by sibbl

1 Answer

0

Don't use the dispatcher when you don't have to. It will introduce the closure semantics. In your method, it does not make sense, even if you were in another synchronization context. Since there is nothing from the GUI-thread involved.

Anyway, I´ve tested your code, but with one difference - I've used StorageFile instead of IsolatedStorage. And it works perfectly.

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        //622Kb: http://www.nasa.gov/sites/default/files/styles/1920x1080_autoletterbox/public/pia17147.jpg?itok=6jErm40V
        //2.7Mb: http://www.nasa.gov/sites/default/files/304_lunar_transit_14-00_ut_0.jpg
        StorageFile imageFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(@"Assets\test3.jpg");
        MemoryStream mz;
        using (var z = await imageFile.OpenStreamForReadAsync())
        {
            if (z.Length > int.MaxValue) return;
            mz = new MemoryStream((int)z.Length);
            var buffer = new byte[4096];

            while (mz.Length < z.Length)
            {
                var readCount = z.Read(buffer, 0, Math.Min(buffer.Length, (int)(z.Length - mz.Length)));
                if (readCount <= 0)
                {
                    throw new NotSupportedException();
                }
                mz.Write(buffer, 0, readCount);
            }                
        }

        var bmp = new BitmapImage();
        bmp.SetSource(mz);
        //Deployment.Current.Dispatcher.BeginInvoke(() => img.Source = bmp); // if in another sync context only
        img.Source = bmp;
    }
answered on Stack Overflow Feb 3, 2014 by JonPall

User contributions licensed under CC BY-SA 3.0