This project has moved. For the latest updates, please go here.

Using async/await to prevent MagickCacheErrorException

Mar 27, 2014 at 4:30 PM
Edited Mar 27, 2014 at 4:34 PM
I have tried for each image in the listbox to do
private void ExtractThumbnail()
{
  Task.Factory.StartNew(() =>
  {
    using (MagickImage image = new MagickImage(fullPath))
    {
        image.Thumbnail(0, 100);
        ImageSource mythumb = loadBitmap(image.ToBitmap());
        if (mythumb.CanFreeze) mythumb.Freeze();
        Thumbnail = mythumb;
    }
but that leads to ImageMagick.MagickCacheErrorException.

Without Task.Factory it does not give me the error but UI is completely unreponsive until all images are there.

If I don't use Taks.Factory and set
<Image Source="{Binding Thumbnail, IsAsync=True}"
then I get the error again

Is there a way to use async/await on the line
using (MagickImage image = new MagickImage(fullPath))
or some other way to prevent the error and get all thumbnails?
Coordinator
Mar 28, 2014 at 10:21 AM
How many images are you trying to load and did you change the ResourceLimits? What is the message in the MagickCacheErrorException?

Does the image.ToImageSource() method not work for you or don't you know it exists?
Mar 28, 2014 at 9:18 PM
It looks like several magick huge tempfiles (up to 1GB) filled up HDD and the error was that there was not enough space. I erased all those files and now there are no errors any more even with TaskFactory.
I did not know how to use ResourceLimits in the above code. I have ObservableCollection of FileData in which I have above the method. I believe it creates as many as it can fit in threadpool. Is there still better way to use your library that you can recommend?

Great that you have implemented ToImageSource(), I will switch to yours.
Coordinator
Mar 28, 2014 at 9:42 PM
You don't have to use ResourceLimits, I was just wondering if you did.

Magick.NET can leave tempfiles if it exists abnormally (for example stopping the debugger in the middle of execution). Magick.NET will use tempfiles when there is not enough memory available. And this really slows down the execution. Maybe you should lower the size of your threadpool to make sure all your images can fit inside the memory. This should be faster then using disk cache.

p.s. I contacted your through Codeplex to ask you if you can check if https://magick.codeplex.com/workitem/1188 is fixed.
Mar 28, 2014 at 10:14 PM
Is it possible to create separate thread pool for this operation only? Maybe it would be enough to have one? How CPU intensive is loading image and resizing it; does is make sense to have threads?
Coordinator
Mar 29, 2014 at 6:52 PM
It really depends on the type of image how CPU intensive reading your image is. And the more pixels you have the longer it takes to resize.

It does make sense to have threads but maybe you should use the LimitedConcurrencyLevelTaskScheduler (an example can be found here: http://msdn.microsoft.com/en-us/library/ee789351.aspx) to limit the number of threads.
Mar 31, 2014 at 3:17 PM
Thanks! I implemented it and it works great. It does not seem much slower with 2 threads in comparison to having all available threads working on it, but at least I am sure that 20 threads will not try opening 30MP images and run out of memory.