Example #1
0
        /// <summary>
        /// Caches the given object to the Application's ImageCache
        /// and returns the uri of the cached file.
        /// </summary>
        /// <param name="objectToCache">Object to cache</param>
        /// <param name="cacheFileName">Name of the cache file</param>
        /// <param name="progressHandler">Delegate for handling progress</param>
        /// <returns>Uri</returns>
        public Task <Uri> GetCachedUriAsync(object objectToCache, string cacheFileName,
                                            CacheProgressHandler progressHandler = null)
        {
            // Check if the objectToCache is a valid Uri
            var uri = objectToCache as Uri;

            if (uri == null)
            {
                // Is the objectToCache a string representing a Uri?
                var uriString = objectToCache as string;
                if (uriString != null)
                {
                    // Try creating the Uri from the uriString
                    if (!(Uri.TryCreate(uriString, UriKind.RelativeOrAbsolute, out uri)))
                    {
                        return(null);
                    }
                }
            }

            // Caching indicates only 80% of the task completed i.e. 80% progress,
            // Progress will be 100% only when the image is loaded successfully on the ImageFrame
            progressHandler?.Invoke(80);
            // Since the given Uri is contained within the Application data or package, there
            // is no need to cache it. Just return the same uri.
            return(Task.Run(() => uri));
        }
        /// <summary>
        /// Caches the given object to the Application's ImageCache
        /// and returns the uri of the cached file.
        /// </summary>
        /// <param name="objectToCache">Object to cache</param>
        /// <param name="cacheFileName">Name of the cache file</param>
        /// <param name="progressHandler">Delegate for handling progress</param>
        /// <returns>Uri</returns>
        public async Task<Uri> GetCachedUriAsync(object objectToCache, string cacheFileName,
            CacheProgressHandler progressHandler = null)
        {
            // Check if the objectToCache is a valid StorageFile
            var inputFile = objectToCache as StorageFile;
            if (inputFile == null)
                return null;

            // Calculate the expiry date
            var expirationDate = DateTime.Now.Subtract(ImageCache.CacheDuration);
            // Get the cache folder location
            var cacheFolder = await ImageCache.GetCacheFolderAsync();
            if (cacheFolder == null)
                return null;

            // Report Progress
            progressHandler?.Invoke(0);

            // Get the cache file corresponding to the cacheFileName
            var cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile;

            // Has the cache file expired or does it not exist?
            if (await cacheFile.IsNullOrExpired(expirationDate))
            {
                try
                {
                    // Report Progress
                    progressHandler?.Invoke(10);

                    // Copy the storage file to the cacheFolder. If the file already exists, overwrite it
                    await inputFile.CopyAsync(cacheFolder, cacheFileName, NameCollisionOption.ReplaceExisting);

                    // Report Progress
                    // Caching indicates only 80% of the task completed i.e. 80% progress,
                    // Progress will be 100% only when the image is loaded successfully on the ImageFrame
                    progressHandler?.Invoke(80);
                }
                catch (Exception)
                {
                    // In case any exception occurs during the copying of the StorageFile
                    // delete the cacheFile and return a 'null' Uri
                    cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile;
                    if (cacheFile != null)
                    {
                        await cacheFile.DeleteAsync();
                    }

                    // Report Progress
                    progressHandler?.Invoke(-1);

                    return null;
                }
            }

            // Report Progress
            progressHandler?.Invoke(80);

            // Now that we have a valid cached file for the Uri, return the Uri of the cached inputFile
            return new Uri($"ms-appdata:///temp/{ImageCache.CacheFolderName}/{cacheFileName}");
        }
Example #3
0
 /// <summary>
 /// Since the given Uri is contained within the Application data or package, there
 /// is no need to cache it. Just return the same uri.
 /// </summary>
 /// <param name="uri">Uri to cache</param>
 /// <param name="cacheFileName">Hash of the Uri</param>
 /// <param name="progressHandler">Delegate for handling progress</param>
 /// <returns>Uri</returns>
 public Task <Uri> GetCachedUriAsync(Uri uri, string cacheFileName, CacheProgressHandler progressHandler = null)
 {
     // Caching indicates only half of the task completed i.e. 50% progress,
     // Progress will be 100% only when the image is loaded successfully on the
     // CompositionImageFrame
     progressHandler?.Invoke(50);
     return(Task.Run(() => uri));
 }
        /// <summary>
        /// Caches the given object to the Application's ImageCache
        /// and returns the uri of the cached file.
        /// </summary>
        /// <param name="objectToCache">Object to cache</param>
        /// <param name="progressHandler">Delegate for handling progress</param>
        /// <returns>Uri of the cached file</returns>
        public static async Task <Uri> GetCachedUriAsync(object objectToCache,
                                                         CacheProgressHandler progressHandler = null)
        {
            if (objectToCache == null)
            {
                return(null);
            }

            Task <Uri> task;

            // Get the hashed value of the object
            var hashKey = await GetHashedFileNameAsync(objectToCache);

            // Check if another task, requesting the cached file of
            // the same object, exists
            lock (ConcurrentCacheTasks)
            {
                if (ConcurrentCacheTasks.ContainsKey(hashKey))
                {
                    task = ConcurrentCacheTasks[hashKey];
                }
                else
                {
                    var cacheHandler = CacheHandlers.FirstOrDefault(h => h.CanCache(objectToCache));
                    if (cacheHandler == null)
                    {
                        return(null);
                    }

                    task = cacheHandler.GetCachedUriAsync(objectToCache, hashKey, progressHandler);
                    ConcurrentCacheTasks.Add(hashKey, task);
                }
            }

            // Wait for the task to complete
            try
            {
                return(await task);
            }
            catch (Exception)
            {
                return(null);
            }
            finally
            {
                lock (ConcurrentCacheTasks)
                {
                    if (ConcurrentCacheTasks.ContainsKey(hashKey))
                    {
                        ConcurrentCacheTasks.Remove(hashKey);
                    }
                }
            }
        }
        /// <summary>
        /// Caches the image obtained from the given Uri to the ImageCache
        /// and provides the Uri to the cached file.
        /// </summary>
        /// <param name="uri">Uri of the image</param>
        /// <param name="progressHandler">Delegate for handling progress</param>
        /// <returns>Uri of the cached file</returns>
        public static async Task <Uri> GetCachedUriAsync(Uri uri, CacheProgressHandler progressHandler = null)
        {
            if (uri == null)
            {
                return(null);
            }

            Task <Uri> task;

            // Get the hashed value of the Uri
            var hashKey = GetHashedFileName(uri);

            // Check if another task requesting the the same Uri exists
            lock (ConcurrentUriTasks)
            {
                if (ConcurrentUriTasks.ContainsKey(hashKey))
                {
                    task = ConcurrentUriTasks[hashKey];
                }
                else
                {
                    var cacheHandler = UriCacheHandlers.FirstOrDefault(h => h.CanCache(uri.Scheme));
                    if (cacheHandler == null)
                    {
                        return(null);
                    }

                    task = cacheHandler.GetCachedUriAsync(uri, hashKey, progressHandler);
                    ConcurrentUriTasks.Add(hashKey, task);
                }
            }

            // Wait for the task to complete
            try
            {
                return(await task);
            }
            catch (Exception)
            {
                return(null);
            }
            finally
            {
                lock (ConcurrentUriTasks)
                {
                    if (ConcurrentUriTasks.ContainsKey(hashKey))
                    {
                        ConcurrentUriTasks.Remove(hashKey);
                    }
                }
            }
        }
        /// <summary>
        /// Caches the given object to the Application's ImageCache
        /// and returns the uri of the cached file.
        /// </summary>
        /// <param name="objectToCache">Object to cache</param>
        /// <param name="cacheFileName">Name of the cache file</param>
        /// <param name="progressHandler">Delegate for handling progress</param>
        /// <returns>Uri</returns>
        public async Task <Uri> GetCachedUriAsync(object objectToCache, string cacheFileName,
                                                  CacheProgressHandler progressHandler = null)
        {
            // Check if the objectToCache is a valid IRandomAccessStream
            var stream = objectToCache as IRandomAccessStream;

            if ((stream == null) || !stream.CanRead)
            {
                return(null);
            }

            // Calculate the expiry date
            var expirationDate = DateTime.Now.Subtract(ImageCache.CacheDuration);
            // Get the cache folder location
            var cacheFolder = await ImageCache.GetCacheFolderAsync();

            if (cacheFolder == null)
            {
                return(null);
            }

            // Report Progress
            progressHandler?.Invoke(0);

            // Get the cache file corresponding to the cacheFileName
            var cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile;

            // Has the cache file expired or does it not exist?
            if (await cacheFile.IsNullOrExpired(expirationDate))
            {
                try
                {
                    // Create/Recreate the cache file
                    cacheFile = await cacheFolder.CreateFileAsync(cacheFileName, CreationCollisionOption.ReplaceExisting);

                    // Open the cache file for writing
                    using (var cacheStream = await cacheFile.OpenAsync(FileAccessMode.ReadWrite))
                    {
                        // Start reading the content as a stream
                        using (var inputStream = stream.GetInputStreamAt(0))
                        {
                            ulong totalBytesRead     = 0;
                            var   prevProgress       = -1;
                            var   totalContentLength = stream.Size;
                            if (totalContentLength <= 0UL)
                            {
                                prevProgress = 0;
                            }
                            while (true)
                            {
                                // Read from the stream
                                IBuffer buffer = new Windows.Storage.Streams.Buffer(2048);
                                buffer = await inputStream.ReadAsync(buffer, buffer.Capacity,
                                                                     InputStreamOptions.None);

                                if (buffer.Length == 0)
                                {
                                    // There is nothing else to read
                                    break;
                                }

                                // The following code can be used to report progress
                                totalBytesRead += buffer.Length;
                                if (totalContentLength > 0UL)
                                {
                                    // We will report a progress percent between 0%-80% because caching represents 80%
                                    // of the task of displaying the image. The other 20% requires successful loading
                                    // of the cached image.
                                    var progress =
                                        (int)Math.Round((totalBytesRead * 80) / (double)totalContentLength);
                                    if (progress != prevProgress)
                                    {
                                        // Report Progress
                                        progressHandler?.Invoke(progress);
                                        prevProgress = progress;
                                    }
                                }
                                else
                                {
                                    prevProgress = Math.Min(prevProgress + 1, 80);
                                    // Report Progress
                                    progressHandler?.Invoke(prevProgress);
                                }

                                // Write to cache file
                                await cacheStream.WriteAsync(buffer);
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    // In case any exception occurs during the copying of the StorageFile
                    // delete the cacheFile and return a 'null' Uri
                    cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile;

                    if (cacheFile != null)
                    {
                        await cacheFile.DeleteAsync();
                    }

                    // Report Progress
                    progressHandler?.Invoke(-1);

                    return(null);
                }
            }

            // Report Progress
            // Caching indicates only half of the task completed i.e. 50% progress,
            // Progress will be 100% only when the image is loaded successfully on the ImageFrame
            progressHandler?.Invoke(80);

            // Now that we have a valid cached file for the Uri, return the Uri of the cached inputFile
            return(new Uri($"ms-appdata:///temp/{ImageCache.CacheFolderName}/{cacheFileName}"));
        }
        /// <summary>
        /// Caches the given object to the Application's ImageCache
        /// and returns the uri of the cached file.
        /// </summary>
        /// <param name="objectToCache">Object to cache</param>
        /// <param name="cacheFileName">Name of the cache file</param>
        /// <param name="progressHandler">Delegate for handling progress</param>
        /// <returns>Uri</returns>
        public async Task<Uri> GetCachedUriAsync(object objectToCache, string cacheFileName,
            CacheProgressHandler progressHandler = null)
        {
            // Check if the objectToCache is a valid Uri
            var uri = objectToCache as Uri;
            if (uri == null)
            {
                // Is the objectToCache a string representing a Uri?
                var uriString = objectToCache as string;
                if (uriString != null)
                {
                    // Try creating the Uri from the uriString
                    if (!(Uri.TryCreate(uriString, UriKind.RelativeOrAbsolute, out uri)))
                    {
                        return null;
                    }
                }
            }

            // Calculate the expiry date
            var expirationDate = DateTime.Now.Subtract(ImageCache.CacheDuration);
            // Get the cache folder location
            var cacheFolder = await ImageCache.GetCacheFolderAsync();
            if (cacheFolder == null)
                return null;

            // Report Progress
            progressHandler?.Invoke(0);

            // Get the cache file corresponding to the cacheFileName
            var cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile;

            // Has the cache file expired or does it not exist?
            if (await cacheFile.IsNullOrExpired(expirationDate))
            {
                try
                {
                    // Create/Recreate the cache file
                    cacheFile = await cacheFolder.CreateFileAsync(cacheFileName, CreationCollisionOption.ReplaceExisting);

                    using (var httpClient = new HttpClient())
                    {
                        // Use HttpCompletionOption.ResponseHeadersRead for the GetAsync call so that it returns as 
                        // soon as response headers are received and not when the whole response is received
                        using (var response = await httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead))
                        {
                            // If respose status is not success then raise exception
                            response.EnsureSuccessStatusCode();
                            // Open the cache file for writing
                            using (var cacheStream = await cacheFile.OpenAsync(FileAccessMode.ReadWrite))
                            {
                                // Start reading the content as a stream
                                using (var inputStream = await response.Content.ReadAsInputStreamAsync())
                                {
                                    ulong totalBytesRead = 0;
                                    var prevProgress = -1;
                                    var totalContentLength = response.Content.Headers.ContentLength ?? 0UL;
                                    while (true)
                                    {
                                        // Read from the stream
                                        IBuffer buffer = new Windows.Storage.Streams.Buffer(2048);
                                        buffer = await inputStream.ReadAsync(buffer, buffer.Capacity,
                                                                             InputStreamOptions.None);

                                        if (buffer.Length == 0)
                                        {
                                            // There is nothing else to read
                                            break;
                                        }

                                        // The following code can be used to report progress
                                        totalBytesRead += buffer.Length;
                                        if (totalContentLength > 0UL)
                                        {
                                            // We will report a progress percent between 0%-80% because caching represents 80%
                                            // of the task of displaying the image. The other 20% requires successful loading 
                                            // of the cached image.
                                            var progress =
                                                (int)Math.Round((totalBytesRead * 80) / (double)totalContentLength);
                                            if (progress != prevProgress)
                                            {
                                                // Report Progress
                                                progressHandler?.Invoke(progress);
                                                prevProgress = progress;
                                            }
                                        }
                                        else
                                        {
                                            prevProgress = Math.Min(prevProgress + 1, 80);
                                            // Report Progress
                                            progressHandler?.Invoke(prevProgress);
                                        }

                                        // Write to cache file
                                        await cacheStream.WriteAsync(buffer);
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    // In case any exception occurs during the downloading or caching
                    // delete the cacheFile and return a 'null' Uri
                    cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile;
                    if (cacheFile != null)
                    {
                        await cacheFile.DeleteAsync();
                    }

                    // Report Progress
                    progressHandler?.Invoke(-1);

                    return null;
                }
            }

            // Report Progress
            // Caching indicates only half of the task completed i.e. 50% progress,
            // Progress will be 100% only when the image is loaded successfully on the ImageFrame
            progressHandler?.Invoke(80);

            // Now that we have a valid cached file for the Uri, return the Uri of the cached inputFile
            return new Uri($"ms-appdata:///temp/{ImageCache.CacheFolderName}/{cacheFileName}");
        }
        /// <summary>
        /// Caches the given object to the Application's ImageCache
        /// and returns the uri of the cached file.
        /// </summary>
        /// <param name="objectToCache">Object to cache</param>
        /// <param name="cacheFileName">Name of the cache file</param>
        /// <param name="progressHandler">Delegate for handling progress</param>
        /// <returns>Uri</returns>
        public async Task <Uri> GetCachedUriAsync(object objectToCache, string cacheFileName,
                                                  CacheProgressHandler progressHandler = null)
        {
            // Check if the objectToCache is a valid Uri
            var uri = objectToCache as Uri;

            if (uri == null)
            {
                // Is the objectToCache a string representing a Uri?
                var uriString = objectToCache as string;
                if (uriString != null)
                {
                    // Try creating the Uri from the uriString
                    if (!(Uri.TryCreate(uriString, UriKind.RelativeOrAbsolute, out uri)))
                    {
                        return(null);
                    }
                }
            }

            // Calculate the expiry date
            var expirationDate = DateTime.Now.Subtract(ImageCache.CacheDuration);
            // Get the cache folder location
            var cacheFolder = await ImageCache.GetCacheFolderAsync();

            if (cacheFolder == null)
            {
                return(null);
            }

            // Report Progress
            progressHandler?.Invoke(0);

            // Get the cache file corresponding to the cacheFileName
            var cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile;

            // Has the cache file expired or does it not exist?
            if (await cacheFile.IsNullOrExpired(expirationDate))
            {
                try
                {
                    // Create/Recreate the cache file
                    cacheFile = await cacheFolder.CreateFileAsync(cacheFileName, CreationCollisionOption.ReplaceExisting);

                    using (var httpClient = new HttpClient())
                    {
                        // Use HttpCompletionOption.ResponseHeadersRead for the GetAsync call so that it returns as
                        // soon as response headers are received and not when the whole response is received
                        using (var response = await httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead))
                        {
                            // If respose status is not success then raise exception
                            response.EnsureSuccessStatusCode();
                            // Open the cache file for writing
                            using (var cacheStream = await cacheFile.OpenAsync(FileAccessMode.ReadWrite))
                            {
                                // Start reading the content as a stream
                                using (var inputStream = await response.Content.ReadAsInputStreamAsync())
                                {
                                    ulong totalBytesRead     = 0;
                                    var   prevProgress       = -1;
                                    var   totalContentLength = response.Content.Headers.ContentLength ?? 0UL;
                                    while (true)
                                    {
                                        // Read from the stream
                                        IBuffer buffer = new Windows.Storage.Streams.Buffer(2048);
                                        buffer = await inputStream.ReadAsync(buffer, buffer.Capacity,
                                                                             InputStreamOptions.None);

                                        if (buffer.Length == 0)
                                        {
                                            // There is nothing else to read
                                            break;
                                        }

                                        // The following code can be used to report progress
                                        totalBytesRead += buffer.Length;
                                        if (totalContentLength > 0UL)
                                        {
                                            // We will report a progress percent between 0%-80% because caching represents 80%
                                            // of the task of displaying the image. The other 20% requires successful loading
                                            // of the cached image.
                                            var progress =
                                                (int)Math.Round((totalBytesRead * 80) / (double)totalContentLength);
                                            if (progress != prevProgress)
                                            {
                                                // Report Progress
                                                progressHandler?.Invoke(progress);
                                                prevProgress = progress;
                                            }
                                        }
                                        else
                                        {
                                            prevProgress = Math.Min(prevProgress + 1, 80);
                                            // Report Progress
                                            progressHandler?.Invoke(prevProgress);
                                        }

                                        // Write to cache file
                                        await cacheStream.WriteAsync(buffer);
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    // In case any exception occurs during the downloading or caching
                    // delete the cacheFile and return a 'null' Uri
                    cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile;

                    if (cacheFile != null)
                    {
                        await cacheFile.DeleteAsync();
                    }

                    // Report Progress
                    progressHandler?.Invoke(-1);

                    return(null);
                }
            }

            // Report Progress
            // Caching indicates only half of the task completed i.e. 50% progress,
            // Progress will be 100% only when the image is loaded successfully on the ImageFrame
            progressHandler?.Invoke(80);

            // Now that we have a valid cached file for the Uri, return the Uri of the cached inputFile
            return(new Uri($"ms-appdata:///temp/{ImageCache.CacheFolderName}/{cacheFileName}"));
        }
        /// <summary>
        /// Caches the given object to the Application's ImageCache
        /// and returns the uri of the cached file.
        /// </summary>
        /// <param name="objectToCache">Object to cache</param>
        /// <param name="cacheFileName">Name of the cache file</param>
        /// <param name="progressHandler">Delegate for handling progress</param>
        /// <returns>Uri</returns>
        public async Task <Uri> GetCachedUriAsync(object objectToCache, string cacheFileName,
                                                  CacheProgressHandler progressHandler = null)
        {
            // Check if the objectToCache is a valid StorageFile
            var inputFile = objectToCache as StorageFile;

            if (inputFile == null)
            {
                return(null);
            }

            // Calculate the expiry date
            var expirationDate = DateTime.Now.Subtract(ImageCache.CacheDuration);
            // Get the cache folder location
            var cacheFolder = await ImageCache.GetCacheFolderAsync();

            if (cacheFolder == null)
            {
                return(null);
            }

            // Report Progress
            progressHandler?.Invoke(0);

            // Get the cache file corresponding to the cacheFileName
            var cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile;

            // Has the cache file expired or does it not exist?
            if (await cacheFile.IsNullOrExpired(expirationDate))
            {
                try
                {
                    // Report Progress
                    progressHandler?.Invoke(10);

                    // Copy the storage file to the cacheFolder. If the file already exists, overwrite it
                    await inputFile.CopyAsync(cacheFolder, cacheFileName, NameCollisionOption.ReplaceExisting);

                    // Report Progress
                    // Caching indicates only 80% of the task completed i.e. 80% progress,
                    // Progress will be 100% only when the image is loaded successfully on the ImageFrame
                    progressHandler?.Invoke(80);
                }
                catch (Exception)
                {
                    // In case any exception occurs during the copying of the StorageFile
                    // delete the cacheFile and return a 'null' Uri
                    cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile;

                    if (cacheFile != null)
                    {
                        await cacheFile.DeleteAsync();
                    }

                    // Report Progress
                    progressHandler?.Invoke(-1);

                    return(null);
                }
            }

            // Report Progress
            progressHandler?.Invoke(80);

            // Now that we have a valid cached file for the Uri, return the Uri of the cached inputFile
            return(new Uri($"ms-appdata:///temp/{ImageCache.CacheFolderName}/{cacheFileName}"));
        }
        /// <summary>
        /// Caches the given object to the Application's ImageCache
        /// and returns the uri of the cached file.
        /// </summary>
        /// <param name="objectToCache">Object to cache</param>
        /// <param name="cacheFileName">Name of the cache file</param>
        /// <param name="progressHandler">Delegate for handling progress</param>
        /// <returns>Uri</returns>
        public async Task<Uri> GetCachedUriAsync(object objectToCache, string cacheFileName,
            CacheProgressHandler progressHandler = null)
        {
            // Check if the objectToCache is a valid IRandomAccessStream
            var stream = objectToCache as IRandomAccessStream;
            if ((stream == null) || !stream.CanRead)
                return null;

            // Calculate the expiry date
            var expirationDate = DateTime.Now.Subtract(ImageCache.CacheDuration);
            // Get the cache folder location
            var cacheFolder = await ImageCache.GetCacheFolderAsync();
            if (cacheFolder == null)
                return null;

            // Report Progress
            progressHandler?.Invoke(0);

            // Get the cache file corresponding to the cacheFileName
            var cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile;

            // Has the cache file expired or does it not exist?
            if (await cacheFile.IsNullOrExpired(expirationDate))
            {
                try
                {
                    // Create/Recreate the cache file
                    cacheFile = await cacheFolder.CreateFileAsync(cacheFileName, CreationCollisionOption.ReplaceExisting);
                    // Open the cache file for writing
                    using (var cacheStream = await cacheFile.OpenAsync(FileAccessMode.ReadWrite))
                    {
                        // Start reading the content as a stream
                        using (var inputStream = stream.GetInputStreamAt(0))
                        {
                            ulong totalBytesRead = 0;
                            var prevProgress = -1;
                            var totalContentLength = stream.Size;
                            if (totalContentLength <= 0UL)
                            {
                                prevProgress = 0;
                            }
                            while (true)
                            {
                                // Read from the stream
                                IBuffer buffer = new Windows.Storage.Streams.Buffer(2048);
                                buffer = await inputStream.ReadAsync(buffer, buffer.Capacity,
                                                                     InputStreamOptions.None);

                                if (buffer.Length == 0)
                                {
                                    // There is nothing else to read
                                    break;
                                }

                                // The following code can be used to report progress
                                totalBytesRead += buffer.Length;
                                if (totalContentLength > 0UL)
                                {
                                    // We will report a progress percent between 0%-80% because caching represents 80%
                                    // of the task of displaying the image. The other 20% requires successful loading 
                                    // of the cached image.
                                    var progress =
                                        (int)Math.Round((totalBytesRead * 80) / (double)totalContentLength);
                                    if (progress != prevProgress)
                                    {
                                        // Report Progress
                                        progressHandler?.Invoke(progress);
                                        prevProgress = progress;
                                    }
                                }
                                else
                                {
                                    prevProgress = Math.Min(prevProgress + 1, 80);
                                    // Report Progress
                                    progressHandler?.Invoke(prevProgress);
                                }

                                // Write to cache file
                                await cacheStream.WriteAsync(buffer);
                            }
                        }
                    }
                }
                catch (Exception)
                {
                    // In case any exception occurs during the copying of the StorageFile
                    // delete the cacheFile and return a 'null' Uri
                    cacheFile = await cacheFolder.TryGetItemAsync(cacheFileName) as StorageFile;
                    if (cacheFile != null)
                    {
                        await cacheFile.DeleteAsync();
                    }

                    // Report Progress
                    progressHandler?.Invoke(-1);

                    return null;
                }
            }

            // Report Progress
            // Caching indicates only half of the task completed i.e. 50% progress,
            // Progress will be 100% only when the image is loaded successfully on the ImageFrame
            progressHandler?.Invoke(80);

            // Now that we have a valid cached file for the Uri, return the Uri of the cached inputFile
            return new Uri($"ms-appdata:///temp/{ImageCache.CacheFolderName}/{cacheFileName}");
        }
        /// <summary>
        /// Caches the given object to the Application's ImageCache
        /// and returns the uri of the cached file.
        /// </summary>
        /// <param name="objectToCache">Object to cache</param>
        /// <param name="progressHandler">Delegate for handling progress</param>
        /// <returns>Uri of the cached file</returns>
        public static async Task<Uri> GetCachedUriAsync(object objectToCache,
            CacheProgressHandler progressHandler = null)
        {
            if (objectToCache == null)
                return null;

            Task<Uri> task;

            // Get the hashed value of the object
            var hashKey = await GetHashedFileNameAsync(objectToCache);

            // Check if another task, requesting the cached file of 
            // the same object, exists
            lock (ConcurrentCacheTasks)
            {
                if (ConcurrentCacheTasks.ContainsKey(hashKey))
                {
                    task = ConcurrentCacheTasks[hashKey];
                }
                else
                {
                    var cacheHandler = CacheHandlers.FirstOrDefault(h => h.CanCache(objectToCache));
                    if (cacheHandler == null)
                        return null;

                    task = cacheHandler.GetCachedUriAsync(objectToCache, hashKey, progressHandler);
                    ConcurrentCacheTasks.Add(hashKey, task);
                }
            }

            // Wait for the task to complete
            try
            {
                return await task;
            }
            catch (Exception)
            {
                return null;
            }
            finally
            {
                lock (ConcurrentCacheTasks)
                {
                    if (ConcurrentCacheTasks.ContainsKey(hashKey))
                    {
                        ConcurrentCacheTasks.Remove(hashKey);
                    }
                }
            }
        }
        /// <summary>
        /// Caches the given object to the Application's ImageCache
        /// and returns the uri of the cached file.
        /// </summary>
        /// <param name="objectToCache">Object to cache</param>
        /// <param name="cacheFileName">Name of the cache file</param>
        /// <param name="progressHandler">Delegate for handling progress</param>
        /// <returns>Uri</returns>
        public Task<Uri> GetCachedUriAsync(object objectToCache, string cacheFileName,
            CacheProgressHandler progressHandler = null)
        {
            // Check if the objectToCache is a valid Uri
            var uri = objectToCache as Uri;
            if (uri == null)
            {
                // Is the objectToCache a string representing a Uri?
                var uriString = objectToCache as string;
                if (uriString != null)
                {
                    // Try creating the Uri from the uriString
                    if (!(Uri.TryCreate(uriString, UriKind.RelativeOrAbsolute, out uri)))
                    {
                        return null;
                    }
                }
            }

            // Caching indicates only 80% of the task completed i.e. 80% progress,
            // Progress will be 100% only when the image is loaded successfully on the ImageFrame
            progressHandler?.Invoke(80);
            // Since the given Uri is contained within the Application data or package, there
            // is no need to cache it. Just return the same uri.
            return Task.Run(() => uri);
        }