public async Task RunAsync() { LoadingResult loadingResult = LoadingResult.Failed; bool success = false; try { if (IsCompleted || IsCancelled || ImageService.ExitTasksEarly) { throw new OperationCanceledException(); } ThrowIfCancellationRequested(); // LOAD IMAGE if (!(await TryLoadFromMemoryCacheAsync().ConfigureAwait(false))) { Logger.Debug(string.Format("Generating/retrieving image: {0}", Key)); var resolver = Parameters.CustomDataResolver ?? DataResolverFactory.GetResolver(Parameters.Path, Parameters.Source, Parameters, Configuration); resolver = new WrappedDataResolver(resolver); var imageData = await resolver.Resolve(Parameters.Path, Parameters, CancellationTokenSource.Token).ConfigureAwait(false); loadingResult = imageData.Item2; using (imageData.Item1) { ImageInformation = imageData.Item3; ImageInformation.SetKey(Key, Parameters.CustomCacheKey); ImageInformation.SetPath(Parameters.Path); ThrowIfCancellationRequested(); // Preload if (Parameters.Preload && Parameters.CacheType.HasValue && Parameters.CacheType.Value == CacheType.Disk) { if (loadingResult == LoadingResult.Internet) { Logger?.Debug(string.Format("DownloadOnly success: {0}", Key)); } success = true; return; } ThrowIfCancellationRequested(); var image = await GenerateImageAsync(Parameters.Path, Parameters.Source, imageData.Item1, imageData.Item3, true, false).ConfigureAwait(false); ThrowIfCancellationRequested(); try { BeforeLoading(image, false); if (image != default(TImageContainer) && CanUseMemoryCache) { MemoryCache.Add(Key, imageData.Item3, image); } ThrowIfCancellationRequested(); bool isFadeAnimationEnabled = Parameters.FadeAnimationEnabled ?? Configuration.FadeAnimationEnabled; await SetTargetAsync(image, isFadeAnimationEnabled).ConfigureAwait(false); } finally { AfterLoading(image, false); } } } success = true; } catch (Exception ex) { if (ex is OperationCanceledException || ex is ObjectDisposedException) { if (Configuration.VerboseLoadingCancelledLogging) { Logger.Debug(string.Format("Image loading cancelled: {0}", Key)); } } else { if (_clearCacheOnOutOfMemory && ex is OutOfMemoryException) { MemoryCache.Clear(); } Logger.Error(string.Format("Image loading failed: {0}", Key), ex); if (Configuration.ExecuteCallbacksOnUIThread && Parameters?.OnError != null) { await MainThreadDispatcher.PostAsync(() => { Parameters?.OnError?.Invoke(ex); }).ConfigureAwait(false); } else { Parameters?.OnError?.Invoke(ex); } try { // Error placeholder if enabled if (!Parameters.Preload && !string.IsNullOrWhiteSpace(Parameters.ErrorPlaceholderPath)) { await ShowPlaceholder(Parameters.ErrorPlaceholderPath, KeyForErrorPlaceholder, Parameters.ErrorPlaceholderSource, false).ConfigureAwait(false); } } catch (Exception ex2) { if (!(ex2 is OperationCanceledException)) { Logger.Error(string.Format("Image loading failed: {0}", Key), ex); } } } } finally { try { if (CancellationTokenSource?.IsCancellationRequested == false) { CancellationTokenSource.Cancel(); } } catch (Exception) { } IsCompleted = true; using (Parameters) { if (Configuration.ExecuteCallbacksOnUIThread && Parameters?.OnFinish != null) { await MainThreadDispatcher.PostAsync(() => { if (success) { Parameters?.OnSuccess?.Invoke(ImageInformation, loadingResult); } Parameters?.OnFinish?.Invoke(this); }).ConfigureAwait(false); } else { if (success) { Parameters?.OnSuccess?.Invoke(ImageInformation, loadingResult); } Parameters?.OnFinish?.Invoke(this); } ImageService.RemovePendingTask(this); } } }
void SetKeys() { KeyRaw = Parameters.Path; if (Parameters.Source == ImageSource.Stream) { if (!string.IsNullOrWhiteSpace(Parameters.StreamChecksum)) { CanUseMemoryCache = true; KeyRaw = Parameters.StreamChecksum; } else { CanUseMemoryCache = false; KeyRaw = string.Concat("Stream_", Guid.NewGuid().ToString("N")); } } if (!string.IsNullOrWhiteSpace(Parameters.CustomCacheKey)) { CanUseMemoryCache = true; KeyRaw = Parameters.CustomCacheKey; } if (Parameters.CacheType == CacheType.Disk) { CanUseMemoryCache = false; } if (string.IsNullOrWhiteSpace(KeyRaw)) { KeyRaw = Guid.NewGuid().ToString("N"); } var vect = Parameters.CustomDataResolver as IVectorDataResolver; if (vect != null) { if (vect.ReplaceStringMap == null || vect.ReplaceStringMap.Count == 0) { KeyRaw = string.Format("{0};(size={1}x{2},dip={3})", KeyRaw, vect.VectorWidth, vect.VectorHeight, vect.UseDipUnits); } else { KeyRaw = string.Format("{0};(size={1}x{2},dip={3},replace=({4}))", KeyRaw, vect.VectorWidth, vect.VectorHeight, vect.UseDipUnits, string.Join(",", vect.ReplaceStringMap.Select(x => string.Format("{0}/{1}", x.Key, x.Value)).OrderBy(v => v))); } } KeyDownsamplingOnly = string.Empty; if (Parameters.DownSampleSize != null && (Parameters.DownSampleSize.Item1 > 0 || Parameters.DownSampleSize.Item2 > 0)) { if (Parameters.DownSampleUseDipUnits) { KeyDownsamplingOnly = string.Concat(";", DpiToPixels(Parameters.DownSampleSize.Item1), "x", DpiToPixels(Parameters.DownSampleSize.Item2)); } else { KeyDownsamplingOnly = string.Concat(";", Parameters.DownSampleSize.Item1, "x", Parameters.DownSampleSize.Item2); } } KeyTransformationsOnly = string.Empty; if (Parameters.Transformations != null && Parameters.Transformations.Count > 0) { KeyTransformationsOnly = string.Concat(";", string.Join(";", Parameters.Transformations.Select(t => t.Key))); } Key = string.Concat(KeyRaw, KeyDownsamplingOnly, KeyTransformationsOnly); KeyWithoutTransformations = string.Concat(KeyRaw, KeyDownsamplingOnly); if (!string.IsNullOrWhiteSpace(Parameters.LoadingPlaceholderPath)) { if (TransformPlaceholders) { KeyForLoadingPlaceholder = string.Concat(Parameters.LoadingPlaceholderPath, KeyDownsamplingOnly, KeyTransformationsOnly); } else { KeyForLoadingPlaceholder = string.Concat(Parameters.LoadingPlaceholderPath, KeyDownsamplingOnly); } var vectLo = Parameters.CustomLoadingPlaceholderDataResolver as IVectorDataResolver; if (vectLo != null) { if (vectLo.ReplaceStringMap == null || vectLo.ReplaceStringMap.Count == 0) { KeyForLoadingPlaceholder = string.Format("{0};(size={1}x{2},dip={3})", KeyForLoadingPlaceholder, vectLo.VectorWidth, vectLo.VectorHeight, vectLo.UseDipUnits); } else { KeyForLoadingPlaceholder = string.Format("{0};(size={1}x{2},dip={3},replace=({4}))", KeyForLoadingPlaceholder, vectLo.VectorWidth, vectLo.VectorHeight, vectLo.UseDipUnits, string.Join(",", vectLo.ReplaceStringMap.Select(x => string.Format("{0}/{1}", x.Key, x.Value)).OrderBy(v => v))); } } } if (!string.IsNullOrWhiteSpace(Parameters.ErrorPlaceholderPath)) { if (TransformPlaceholders) { KeyForErrorPlaceholder = string.Concat(Parameters.ErrorPlaceholderPath, KeyDownsamplingOnly, KeyTransformationsOnly); } else { KeyForErrorPlaceholder = string.Concat(Parameters.ErrorPlaceholderPath, KeyDownsamplingOnly); } var vectEr = Parameters.CustomLoadingPlaceholderDataResolver as IVectorDataResolver; if (vectEr != null) { if (vectEr.ReplaceStringMap == null || vectEr.ReplaceStringMap.Count == 0) { KeyForErrorPlaceholder = string.Format("{0};(size={1}x{2},dip={3})", KeyForErrorPlaceholder, vectEr.VectorWidth, vectEr.VectorHeight, vectEr.UseDipUnits); } else { KeyForErrorPlaceholder = string.Format("{0};(size={1}x{2},dip={3},replace=({4}))", KeyForErrorPlaceholder, vectEr.VectorWidth, vectEr.VectorHeight, vectEr.UseDipUnits, string.Join(",", vectEr.ReplaceStringMap.Select(x => string.Format("{0}/{1}", x.Key, x.Value)).OrderBy(v => v))); } } } ImageInformation.SetKey(Key, Parameters.CustomCacheKey); ImageInformation.SetPath(Parameters.Path); }
public ImageLoaderTask(IMemoryCache <TImageContainer> memoryCache, IDataResolverFactory dataResolverFactory, ITarget <TImageContainer, TImageView> target, TaskParameter parameters, IImageService imageService, Configuration configuration, IMainThreadDispatcher mainThreadDispatcher, bool clearCacheOnOutOfMemory) { _clearCacheOnOutOfMemory = clearCacheOnOutOfMemory; MemoryCache = memoryCache; DataResolverFactory = dataResolverFactory; PlatformTarget = target; ImageService = imageService; Configuration = configuration; MainThreadDispatcher = mainThreadDispatcher; Parameters = parameters; CancellationTokenSource = new CancellationTokenSource(); ImageInformation = new ImageInformation(); CanUseMemoryCache = true; KeyRaw = Parameters.Path; if (Parameters.Source == ImageSource.Stream) { CanUseMemoryCache = false; KeyRaw = string.Concat("Stream_", GetNextStreamIndex()); } if (!string.IsNullOrWhiteSpace(Parameters.CustomCacheKey)) { CanUseMemoryCache = true; KeyRaw = Parameters.CustomCacheKey; } if (string.IsNullOrWhiteSpace(KeyRaw)) { KeyRaw = Guid.NewGuid().ToString("N"); } KeyDownsamplingOnly = string.Empty; if (Parameters.DownSampleSize != null && (Parameters.DownSampleSize.Item1 > 0 || Parameters.DownSampleSize.Item2 > 0)) { KeyDownsamplingOnly = string.Concat(";", Parameters.DownSampleSize.Item1, "x", Parameters.DownSampleSize.Item2); } KeyTransformationsOnly = string.Empty; if (Parameters.Transformations != null && Parameters.Transformations.Count > 0) { KeyTransformationsOnly = string.Concat(string.Join(";", Parameters.Transformations.Select(t => t.Key))); } Key = string.Concat(KeyRaw, KeyDownsamplingOnly, KeyTransformationsOnly); KeyWithoutTransformations = string.Concat(KeyRaw, KeyDownsamplingOnly); if (!string.IsNullOrWhiteSpace(Parameters.LoadingPlaceholderPath)) { if (TransformPlaceholders) { KeyForLoadingPlaceholder = string.Concat(Parameters.LoadingPlaceholderPath, KeyDownsamplingOnly, KeyTransformationsOnly); } else { KeyForLoadingPlaceholder = string.Concat(Parameters.LoadingPlaceholderPath, KeyDownsamplingOnly); } } if (!string.IsNullOrWhiteSpace(Parameters.ErrorPlaceholderPath)) { if (TransformPlaceholders) { KeyForErrorPlaceholder = string.Concat(Parameters.ErrorPlaceholderPath, KeyDownsamplingOnly, KeyTransformationsOnly); } else { KeyForErrorPlaceholder = string.Concat(Parameters.ErrorPlaceholderPath, KeyDownsamplingOnly); } } ImageInformation.SetKey(Key, Parameters.CustomCacheKey); ImageInformation.SetPath(Parameters.Path); Target?.SetImageLoadingTask(this); }