none
Unusual Stalls caused by BitmapSource.Create RRS feed

  • General discussion

  • Hello,

    I have created a small program that causes unusual stalls when a BitmapSource is created. In our software it stalls the whole UI, even if created in a work thread. From the Profiler I was only able to identify that the CachedBitmap constructor takes all the time. The whole thing starts when about 1GB of data is allocated using lots of small objects. So far I have tested this on Windows 7 and 8.1 with the same result. 

    I have created a repository with the source code, I hope someone can help to get a bit deeper into the problem:
    https://github.com/luithefirst/BitmapSourceStall

    1. Compile and Start (no matter Debug/Release, w/wo VS-Debugger)
    2. Close/Cancel OpenFileDialog that is shown
    3. See printed “CreateBitmapSource: <time>” to suddenly jump up to >1000ms

    The data creation loop is configured to generate the necessary amount of data in one or two iterations. As you can see, the first thing is an OpenFileDialog that is prompted. For some really strange reason this is necessary to cause the stalls. Without that dialog, BitmapSource.Create usually finishes in 0ms, but sometimes there are still outlier that take >1000ms, you can try this by commenting the two lines of code.

    I appreciate all help!

    Greetings, 
    Lui


    Tuesday, March 22, 2016 10:42 AM

All replies

  • That's a console app rather than a wpf application and openfiledialog is blocking.

    What UI would you be stalling?

    If you want to create bitmaps in wpf and keep the ui responsive, do so on a different thread to the UI.

    The bitmaps will have thread affinity so you will need to freeze them before you can pass them back to the ui thread successfully.

    myBitMap.Freeze();
    I don't know what you're doing here exactly but you can bind to a byte[] as imagesource - and these have no thread affinity.

    This code here retains ui responsiveness by freeing up the ui for 200 ms between each file read into a List.

        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
            private List<byte[]> picArray = new List<byte[]>();
    
            private async void Button_Click(object sender, RoutedEventArgs e)
            {
                string dir = @"D:\\Pics\\some folder";
                var files = Directory.EnumerateFiles(dir, "*.*", SearchOption.AllDirectories)
                 .Where(s => s.EndsWith(".jpeg") || s.EndsWith(".jpg") || s.EndsWith(".png"));
                foreach (string item in files)
                {
                    byte[] pic = await ReadAllFileAsync(item);
                    picArray.Add(pic);
                    await Task.Delay(200);
                    Debug.WriteLine(item);
                }
            }
            static async Task<byte[]> ReadAllFileAsync(string filename)
            {
                using (var file = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true))
                {
                    byte[] result = new byte[file.Length];
                    await file.ReadAsync(result, 0, (int)file.Length);
                    return result;
                }
            }
        }

    You could instead push that task onto a separate thread and you might want to if these are very large files. Bear in mind you can run out of memory with a lot of large files.


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    Tuesday, March 22, 2016 2:59 PM
    Moderator
  • Thanks for you reply!

    The app in the repository has no UI, since I have removed everything that did not change anything about the issue I have encountered: Something within the CachedBitmap constructor (I cannot identify it, because I could not successfully build matching debug symbol for the PresentationCore.ni.dll) is stalling for an unknown reason.

    Have you executed my demo app and noticed the long time it takes to call BitmapSource.Create after some iterations of the loop that generates "data"?

    The images are tiny (64x64) that are created there and I can usually do this 10k times and more without any stall. In the demo it stalls during the creation of the 3rd batch of 100 images on my machine.

    Yes, in our software we load the images in a workthread, applying Freeze and pushing the update using the Dispatcher, however, even if the BitmapSource is created in this workthread, the UI stalls, I suspect there must be some very deep unmanaged call with some kind of synchronization be happening.

    The only related discussion I could find so far:

    http://stackoverflow.com/questions/28718826/unexplainable-performance-issues-with-bitmapsource-in-wpf

    http://stackoverflow.com/questions/22935617/creating-bitmap-on-background-thread-stalls-render-thread



    • Edited by Lui Sharp Tuesday, March 22, 2016 3:24 PM
    Tuesday, March 22, 2016 3:20 PM
  • I looked at your console app.

    Whilst it's a good idea to produce a minimal representative sample, making your sample a console app is going too far IMO.

    It is no longer a WPF app.

    .

    I don't follow why you are loading hundreds of images, let alone 10,000. What are you going to do with so many images?

    .

    Did you try the code I provided and consider whether byte[] would work for whatever you're doing?


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    Tuesday, March 22, 2016 6:44 PM
    Moderator
  • The 10k was just a benchmark I made and even this huge amount seems to be no problem. Usually we have about 100 icons (generated by the application), they are about the size that I used in the sample code (64x64). The sample currently also only allocates 100 images each time and usually already in the third iteration, this takes 1000ms allocating a single one. The size of the images does not have a significant influence either. 

    I could blow it up to a WPF application again, the result would be the same.

    Your example does not really help, in our application the content of the images is already in memory and I already have the raw byte array.

    Well, maybe the problem does not have todo anything with WPF directly, but I cannot tell, I don't know whats going on in PresentationCore.ni.dll when such an image is allocated.

    Did anyone run the sample code? How long does it take to allocated the BitmapSources?

    Wednesday, March 23, 2016 10:07 AM
  • Since this problem apparently is not directly related to WPF, I have created a thread in the CLR subsection and additionally reported this issue to MS Connect:

    https://social.msdn.microsoft.com/Forums/en-US/5bb908b8-a432-4b4f-a136-e3c503856439/unusual-stalls-in-crl

    https://connect.microsoft.com/VisualStudio/feedback/details/2579672
    Tuesday, April 12, 2016 9:13 AM