Пример #1
0
		/// <summary>
		/// Indicates if the task uses the same native control
		/// </summary>
		/// <returns><c>true</c>, if same native control is used, <c>false</c> otherwise.</returns>
		/// <param name="task">Task to check.</param>
		public override bool UsesSameNativeControl(IImageLoaderTask task)
		{
			var loaderTask = task as ImageLoaderTask;
			if (loaderTask == null)
				return false;
			return UsesSameNativeControl(loaderTask);
		}
 public void CancelLoading()
 {
     if (ImageLoaderTask != null)
     {
         ImageService.Instance.CancelWorkFor(ImageLoaderTask);
         ImageLoaderTask = null;
     }
     
 }
 public virtual void Cancel(IImageLoaderTask task)
 {
     try
     {
         if (task != null && !task.IsCancelled && !task.IsCompleted)
         {
             task.Cancel();
         }
     }
     catch (Exception e)
     {
         Logger.Error(string.Format("Cancelling task failed: {0}", task?.Key), e);
     }
     finally
     {
         task?.Dispose();
         EvictStaleTasks();
     }
 }
Пример #4
0
		/// <summary>
		/// Cancels any pending work for the task.
		/// </summary>
		/// <param name="task">Image loading task to cancel</param>
		/// <returns><c>true</c> if this instance cancel task; otherwise, <c>false</c>.</returns>
		public void Cancel(IImageLoaderTask task)
		{
			try
			{
				if (task != null && !task.IsCancelled && !task.Completed)
				{
					task.Cancel();
				}
			}
			catch (Exception e)
			{
				_logger.Error("Exception occurent trying to cancel the task", e);
			}
			finally
			{
				if (task != null && task.IsCancelled)
					task.Parameters.Dispose(); // this will ensure we don't keep a reference due to callbacks
			}
		}
		public virtual async void LoadImage(IImageLoaderTask task)
		{
			Interlocked.Increment(ref _loadCount);

            EvictStaleTasks();

            if (Configuration.VerbosePerformanceLogging && (_loadCount % 10) == 0)
			{
				LogSchedulerStats();
			}

            if (task?.Parameters?.Source != ImageSource.Stream && string.IsNullOrWhiteSpace(task?.Parameters?.Path))
            {
                Logger.Error("ImageService: null path ignored");
                task?.Dispose();
                return;
            }

			if (task == null)
				return;

            if (task.IsCancelled || task.IsCompleted || ExitTasksEarly)
			{
				task?.Dispose();
				return;
			}

			if (task.Parameters.DelayInMs != null && task.Parameters.DelayInMs > 0)
			{
				await Task.Delay(task.Parameters.DelayInMs.Value).ConfigureAwait(false);
			}

			// If we have the image in memory then it's pointless to schedule the job: just display it straight away
			if (task.CanUseMemoryCache)
			{
                if (await task.TryLoadFromMemoryCacheAsync().ConfigureAwait(false))
                {
                    Interlocked.Increment(ref _statsTotalMemoryCacheHits);
                    task?.Dispose();
                    return;
                }
			}

            _dispatch = _dispatch.ContinueWith(t =>
            {
                try
                {
                    QueueImageLoadingTask(task);
                }
                catch (Exception ex)
                {
                    Logger.Error(string.Format("Image loaded failed: {0}", task?.Key), ex);
                }
            });
        }
        protected Task CreateFrameworkTask(IImageLoaderTask imageLoadingTask)
        {
            var parameters = imageLoadingTask.Parameters;

            var tcs = new TaskCompletionSource<bool>();

            var successCallback = parameters.OnSuccess;
            parameters.Success((size, result) =>
            {
                tcs.TrySetResult(true);
                successCallback?.Invoke(size, result);
            });

            var finishCallback = parameters.OnFinish;
            parameters.Finish(sw =>
            {
                tcs.TrySetResult(false);
                finishCallback?.Invoke(sw);
            });

            return tcs.Task;
        }
Пример #7
0
 /// <summary>
 /// Queue an image loading task.
 /// </summary>
 /// <param name="task">Image loading task.</param>
 public static void LoadImage(IImageLoaderTask task)
 {
     Scheduler.LoadImage(task);
 }
Пример #8
0
 /// <summary>
 /// Cancel any loading work for the given ImageView
 /// </summary>
 /// <param name="task">Image loading task to cancel.</param>
 public static void CancelWorkFor(IImageLoaderTask task)
 {
     Scheduler.Cancel(task);
 }
Пример #9
0
        private void QueueAndGenerateImage(IImageLoaderTask task)
        {
            _logger.Debug(string.Format("Generating/retrieving image: {0}", task.GetKey()));

            int position = Interlocked.Increment(ref _currentPosition);
            var currentPendingTask = new PendingTask() { Position = position, ImageLoadingTask = task, FrameworkWrappingTask = CreateFrameworkTask(task) };

            PendingTask alreadyRunningTaskForSameKey = null;
            lock (_pendingTasksLock)
            {
                alreadyRunningTaskForSameKey = FindSimilarPendingTask(task);
                if (alreadyRunningTaskForSameKey == null)
                {
                    Interlocked.Increment(ref _statsTotalPending);
                    _pendingTasks.Add(currentPendingTask);
                }
                else
                {
                    alreadyRunningTaskForSameKey.Position = position;
                }
            }

            if (alreadyRunningTaskForSameKey == null || !currentPendingTask.ImageLoadingTask.CanUseMemoryCache())
            {
                Run(currentPendingTask);
            }
            else
            {
                WaitForSimilarTask(currentPendingTask, alreadyRunningTaskForSameKey);
            }
        }
Пример #10
0
        /// <summary>
        /// Queue an image loading task.
        /// </summary>
        /// <param name="task">Image loading task.</param>
        public static void LoadImage(IImageLoaderTask task)
        {
            Scheduler.LoadImage(task);
			AddRequestToHistory(task);
        }
Пример #11
0
 public virtual bool IsTaskValid(IImageLoaderTask task) => IsValid;
Пример #12
0
 public override bool IsTaskValid(IImageLoaderTask task)
 {
     return(IsValid);
 }
Пример #13
0
 private void Enqueue(IImageLoaderTask task)
 {
     PendingTasks.Enqueue(task, task.Parameters.Priority ?? GetDefaultPriority(task.Parameters.Source));
 }
Пример #14
0
        protected async Task TakeFromPendingTasksAndRunAsync()
        {
            if (PendingTasks.Count == 0)
            {
                return;
            }

            Dictionary <string, IImageLoaderTask> tasksToRun = null;

            var preloadOrUrlTasksCount = 0;
            var urlTasksCount          = 0;
            var preloadTasksCount      = 0;

            lock (_lock)
            {
                if (RunningTasks.Count >= MaxParallelTasks)
                {
                    urlTasksCount          = RunningTasks.Count(v => v.Value != null && !v.Value.Parameters.Preload && v.Value.Parameters.Source == ImageSource.Url);
                    preloadTasksCount      = RunningTasks.Count(v => v.Value != null && v.Value.Parameters.Preload);
                    preloadOrUrlTasksCount = preloadTasksCount + urlTasksCount;

                    if (preloadOrUrlTasksCount == 0 || preloadOrUrlTasksCount != MaxParallelTasks)
                    {
                        return;
                    }

                    // Allow only half of MaxParallelTasks as additional allowed tasks when preloading occurs to prevent starvation
                    if (RunningTasks.Count - Math.Max(1, Math.Min(preloadOrUrlTasksCount, MaxParallelTasks / 2)) >= MaxParallelTasks)
                    {
                        return;
                    }
                }

                var numberOfTasks = MaxParallelTasks - RunningTasks.Count + Math.Min(preloadOrUrlTasksCount, MaxParallelTasks / 2);
                tasksToRun = new Dictionary <string, IImageLoaderTask>();
                IImageLoaderTask task = null;

                while (tasksToRun.Count < numberOfTasks && PendingTasks.TryDequeue(out task))
                {
                    if (task == null || task.IsCancelled || task.IsCompleted)
                    {
                        continue;
                    }

                    // We don't want to load, at the same time, images that have same key or same raw key at the same time
                    // This way we prevent concurrent downloads and benefit from caches
                    var rawKey = task.KeyRaw;
                    if (RunningTasks.ContainsKey(rawKey) || tasksToRun.ContainsKey(rawKey))
                    {
                        SimilarTasks.Add(task);
                        continue;
                    }

                    if (preloadOrUrlTasksCount != 0)
                    {
                        if (!task.Parameters.Preload && (urlTasksCount == 0 || task.Parameters.Source != ImageSource.Url))
                        {
                            tasksToRun.Add(rawKey, task);
                        }
                        else
                        {
                            Enqueue(task);
                            break;
                        }
                    }
                    else
                    {
                        tasksToRun.Add(rawKey, task);
                    }
                }

                foreach (var item in tasksToRun)
                {
                    RunningTasks.Add(item.Key, item.Value);
                    Interlocked.Increment(ref _statsTotalRunning);
                }
            }

            if (tasksToRun != null && tasksToRun.Count > 0)
            {
                var tasks = tasksToRun.Select(async p =>
                {
                    await Task.Factory.StartNew(async() =>
                    {
                        try
                        {
                            await RunImageLoadingTaskAsync(p.Value).ConfigureAwait(false);
                        }
                        catch (Exception ex)
                        {
                            Logger.Error("TakeFromPendingTasksAndRun exception", ex);
                        }
                    }, CancellationToken.None, TaskCreationOptions.PreferFairness | TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler, TaskScheduler.Default).ConfigureAwait(false);
                });
                await Task.WhenAll(tasks).ConfigureAwait(false);
            }
        }
Пример #15
0
 public virtual bool UsesSameNativeControl(IImageLoaderTask anotherTask)
 {
     return(Target.UsesSameNativeControl(anotherTask));
 }
Пример #16
0
 public abstract bool UsesSameNativeControl(IImageLoaderTask task);
Пример #17
0
        public override bool IsTaskValid(IImageLoaderTask task)
        {
            var controlTask = Control?.GetImageLoaderTask();

            return(IsValid && (controlTask == null || controlTask == task));
        }
Пример #18
0
 protected abstract void SetTaskForTarget(IImageLoaderTask currentTask);
Пример #19
0
 public virtual bool UsesSameNativeControl(IImageLoaderTask task) => false;
Пример #20
0
		private void QueueAndGenerateImage(IImageLoaderTask task)
		{
			_logger.Debug(string.Format("Generating/retrieving image: {0}", task.GetKey()));

			var currentPendingTask = new PendingTask() { ImageLoadingTask = task };
			PendingTask alreadyRunningTaskForSameKey = null;
			lock (_pauseWorkLock)
			{
				lock (_pendingTasksLock)
				{
					alreadyRunningTaskForSameKey = _pendingTasks.FirstOrDefault(t => t.ImageLoadingTask.GetKey() == task.GetKey() && (!t.ImageLoadingTask.IsCancelled));
					if (alreadyRunningTaskForSameKey == null)
						_pendingTasks.Add(currentPendingTask);
				}
			}

			if (alreadyRunningTaskForSameKey == null || !currentPendingTask.ImageLoadingTask.CanUseMemoryCache())
			{
				Run(currentPendingTask);
			}
			else
			{
				WaitForSimilarTask(currentPendingTask, alreadyRunningTaskForSameKey);
			}
		}
Пример #21
0
 public virtual void SetAsEmpty(IImageLoaderTask task)
 {
 }
Пример #22
0
        private PendingTask FindSimilarPendingTask(IImageLoaderTask task)
        {
            // At first check if the exact same items exists in pending tasks (exact same means same transformations, same downsample, ...)
            // Since it will be exactly the same it can be retrieved from memory cache

            string key = task.GetKey(raw: false);
            var alreadyRunningTaskForSameKey = _pendingTasks.FirstOrDefault(t => t.ImageLoadingTask.GetKey(raw: false) == key);

            return alreadyRunningTaskForSameKey;
        }
Пример #23
0
 public virtual void Set(IImageLoaderTask task, TImageContainer image, bool animated)
 {
 }
Пример #24
0
        /// <summary>
        /// Queue an image loading task.
        /// </summary>
        /// <param name="task">Image loading task.</param>
        public void LoadImage(IImageLoaderTask task)
        {
			if (task == null)
				return;

			if (task.Parameters.DelayInMs == null && Config.DelayInMs > 0)
				task.Parameters.Delay(Config.DelayInMs);

			Scheduler.LoadImage(task);
        }
Пример #25
0
 public virtual void SetImageLoadingTask(IImageLoaderTask task)
 {
 }
Пример #26
0
		private static void AddRequestToHistory(IImageLoaderTask task)
		{
			AddRequestToHistory(task.Parameters.Path, task.GetKey());
			AddRequestToHistory(task.Parameters.CustomCacheKey, task.GetKey());
			AddRequestToHistory(task.Parameters.LoadingPlaceholderPath, task.GetKey(task.Parameters.LoadingPlaceholderPath));
			AddRequestToHistory(task.Parameters.ErrorPlaceholderPath, task.GetKey(task.Parameters.ErrorPlaceholderPath));
		}
Пример #27
0
 /// <summary>
 /// Removes a pending image loading task from the work queue.
 /// </summary>
 /// <param name="task">Image loading task to remove.</param>
 public void RemovePendingTask(IImageLoaderTask task)
 {
     Scheduler.RemovePendingTask(task);
 }
Пример #28
0
 /// <summary>
 /// Removes a pending image loading task from the work queue.
 /// </summary>
 /// <param name="task">Image loading task to remove.</param>
 public static void RemovePendingTask(IImageLoaderTask task)
 {
     Scheduler.RemovePendingTask(task);
 }
Пример #29
0
        protected async Task TakeFromPendingTasksAndRunAsync()
        {
            if (PendingTasks.Count == 0)
            {
                return;
            }

            Dictionary <string, IImageLoaderTask> tasksToRun = null;

            int preloadOrUrlTasksCount = 0;
            int urlTasksCount          = 0;
            int preloadTasksCount      = 0;

            lock (_lock)
            {
                if (RunningTasks.Count >= MaxParallelTasks)
                {
                    urlTasksCount          = RunningTasks.Count(v => v.Value != null && (!v.Value.Parameters.Preload && v.Value.Parameters.Source == ImageSource.Url));
                    preloadTasksCount      = RunningTasks.Count(v => v.Value != null && v.Value.Parameters.Preload);
                    preloadOrUrlTasksCount = preloadTasksCount + urlTasksCount;

                    if (preloadOrUrlTasksCount == 0 || preloadOrUrlTasksCount != MaxParallelTasks)
                    {
                        return;
                    }

                    // Allow only half of MaxParallelTasks as additional allowed tasks when preloading occurs to prevent starvation
                    if (RunningTasks.Count - Math.Max(1, Math.Min(preloadOrUrlTasksCount, MaxParallelTasks / 2)) >= MaxParallelTasks)
                    {
                        return;
                    }
                }

                int numberOfTasks = MaxParallelTasks - RunningTasks.Count + Math.Min(preloadOrUrlTasksCount, MaxParallelTasks / 2);
                tasksToRun = new Dictionary <string, IImageLoaderTask>();
                IImageLoaderTask task = null;

                while (tasksToRun.Count < numberOfTasks && PendingTasks.TryDequeue(out task))
                {
                    if (task == null || task.IsCancelled || task.IsCompleted)
                    {
                        continue;
                    }

                    // We don't want to load, at the same time, images that have same key or same raw key at the same time
                    // This way we prevent concurrent downloads and benefit from caches
                    string rawKey = task.KeyRaw;
                    if (RunningTasks.ContainsKey(rawKey) || tasksToRun.ContainsKey(rawKey))
                    {
                        SimilarTasks.Add(task);
                        continue;
                    }

                    if (preloadOrUrlTasksCount != 0)
                    {
                        if (!task.Parameters.Preload && (urlTasksCount == 0 || task.Parameters.Source != ImageSource.Url))
                        {
                            tasksToRun.Add(rawKey, task);
                        }
                        else
                        {
                            Enqueue(task);
                            break;
                        }
                    }
                    else
                    {
                        tasksToRun.Add(rawKey, task);
                    }
                }

                foreach (var item in tasksToRun)
                {
                    RunningTasks.Add(item.Key, item.Value);
                    Interlocked.Increment(ref _statsTotalRunning);
                }
            }

            if (tasksToRun != null && tasksToRun.Count > 0)
            {
                var tasks = tasksToRun.Select(p => RunImageLoadingTaskAsync(p.Value));
                await Task.WhenAll(tasks).ConfigureAwait(false);
            }
        }
Пример #30
0
 public virtual void RemovePendingTask(IImageLoaderTask task)
 {
     lock (_pendingTasksLock)
     {
         PendingTasks.RemoveAll(p => p.ImageLoadingTask == task);
     }
 }
Пример #31
0
        public override void Set(IImageLoaderTask task, NSImage image, bool animated)
        {
            if (task == null || task.IsCancelled)
            {
                return;
            }

            var control = Control;

            if (control == null)
            {
                return;
            }

            bool isXamarinForms  = control.Layer is FFCALayer;
            var  parameters      = task.Parameters;
            var  representations = image.Representations();

            if (representations.Length > 1)
            {
                control.Layer.Contents = null;
                control.Image          = image;
                control.Animates       = true;
                control.SetNeedsDisplay();
                control.CanDrawSubviewsIntoLayer = true;
                if (IsLayoutNeeded(task))
                {
                    control.NeedsLayout = true;
                }
            }
            else
            {
                if (animated)
                {
                    //TODO fade animation
                    if (isXamarinForms)
                    {
                        control.Layer.Contents = image.CGImage;
                    }
                    else
                    {
                        control.Image = image;
                    }

                    control.SetNeedsDisplay();
                    if (IsLayoutNeeded(task))
                    {
                        control.NeedsLayout = true;
                    }
                }
                else
                {
                    if (isXamarinForms)
                    {
                        control.Layer.Contents = image.CGImage;
                    }
                    else
                    {
                        control.Image = image;
                    }

                    control.SetNeedsDisplay();
                    if (IsLayoutNeeded(task))
                    {
                        control.NeedsLayout = true;
                    }
                }
            }
        }
Пример #32
0
        protected void QueueImageLoadingTask(IImageLoaderTask task)
        {
            int position = Interlocked.Increment(ref _currentPosition);
            var currentPendingTask = new PendingTask() { Position = position, ImageLoadingTask = task, FrameworkWrappingTask = CreateFrameworkTask(task) };

            if (task.IsCancelled || task.IsCompleted || ExitTasksEarly)
            {
                task?.Dispose();
                return;
            }

            PendingTask similarRunningTask = null;
            lock (_pendingTasksLock)
            {
                if (!task.Parameters.Preload)
                {
                    foreach (var pendingTask in PendingTasks.ToList()) // FMT: here we need a copy since cancelling will trigger them to be removed, hence collection is modified during enumeration
                    {
                        if (pendingTask.ImageLoadingTask != null && pendingTask.ImageLoadingTask.UsesSameNativeControl(task))
                            pendingTask.ImageLoadingTask.CancelIfNeeded();
                    }

                    EvictStaleTasks();
                }

                similarRunningTask = PendingTasks.FirstOrDefault(t => t.ImageLoadingTask.Key == task.Key);
                if (similarRunningTask == null)
                {
                    Interlocked.Increment(ref _statsTotalPending);
                    PendingTasks.Add(currentPendingTask);
                }
                else
                {
                    similarRunningTask.Position = position;
                }
            }

            if (PauseWork)
                return;

            if (similarRunningTask == null || !currentPendingTask.ImageLoadingTask.CanUseMemoryCache)
            {
                TakeFromPendingTasksAndRun();
            }
            else
            {
                WaitForSimilarTaskFinished(currentPendingTask, similarRunningTask);
            }
        }
Пример #33
0
		public void RemovePendingTask(IImageLoaderTask task)
		{
			lock (_pauseWorkLock)
			{
				lock (_pendingTasksLock)
				{
					var pendingTask = _pendingTasks.FirstOrDefault(t => t.ImageLoadingTask == task);
					if (pendingTask != null)
						_pendingTasks.Remove(pendingTask);
				}
			}
		}
Пример #34
0
 public override bool UsesSameNativeControl(IImageLoaderTask task)
 {
     return(_target.UsesSameNativeControl((ImageLoaderTask)task));
 }
Пример #35
0
 public void CancelWorkFor(IImageLoaderTask task)
 {
     task?.Cancel();
 }
		public abstract bool UsesSameNativeControl(IImageLoaderTask task);
Пример #37
0
 /// <summary>
 /// Cancel any loading work for the given ImageView
 /// </summary>
 /// <param name="task">Image loading task to cancel.</param>
 public static void CancelWorkFor(IImageLoaderTask task)
 {
     Scheduler.Cancel(task);
 }
Пример #38
0
		/// <summary>
		/// Schedules the image loading. If image is found in cache then it returns it, otherwise it loads it.
		/// </summary>
		/// <param name="task">Image loading task.</param>
		public async void LoadImage(IImageLoaderTask task)
		{
			if (task == null)
				return;

			if (task.IsCancelled)
			{
				task.Parameters.Dispose(); // this will ensure we don't keep a reference due to callbacks
				return;
			}

			bool loadedFromCache = await task.PrepareAndTryLoadingFromCacheAsync().ConfigureAwait(false);
			if (loadedFromCache)
			{
				if (task.Parameters.OnFinish != null)
					task.Parameters.OnFinish(task);

				task.Parameters.Dispose(); // this will ensure we don't keep a reference due to callbacks
				return; // image successfully loaded from cache
			}
			
			if (task.IsCancelled || _pauseWork)
			{
				task.Parameters.Dispose(); // this will ensure we don't keep a reference due to callbacks
				return;
			}

			QueueAndGenerateImage(task);
		}
Пример #39
0
		/// <summary>
		/// Indicates if the task uses the same native control
		/// </summary>
		/// <returns><c>true</c>, if same native control is used, <c>false</c> otherwise.</returns>
		/// <param name="task">Task to check.</param>
		public override bool UsesSameNativeControl(IImageLoaderTask task)
		{
			return _target.UsesSameNativeControl((ImageLoaderTask)task);
		}
Пример #40
0
		/// <summary>
		/// Schedules the image loading. If image is found in cache then it returns it, otherwise it loads it.
		/// </summary>
		/// <param name="task">Image loading task.</param>
		public async void LoadImage(IImageLoaderTask task)
		{
			if (task == null)
				return;

			if (task.IsCancelled)
			{
				task.Parameters.Dispose(); // this will ensure we don't keep a reference due to callbacks
				return;
			}

			List<PendingTask> pendingTasksCopy;
			lock (_pendingTasksLock)
			{
				pendingTasksCopy = _pendingTasks.ToList();
			}
			foreach (var pendingTask in pendingTasksCopy)
			{
				if (pendingTask.ImageLoadingTask != null && pendingTask.ImageLoadingTask.UsesSameNativeControl(task))
					pendingTask.ImageLoadingTask.CancelIfNeeded();
			}

			bool loadedFromCache = false;
			if (task.CanUseMemoryCache())
			{
				loadedFromCache = await task.PrepareAndTryLoadingFromCacheAsync().ConfigureAwait(false);
			}

			if (loadedFromCache)
			{
				if (task.Parameters.OnFinish != null)
					task.Parameters.OnFinish(task);
				
				task.Dispose();
				return; // image successfully loaded from cache
			}
			
			if (task.IsCancelled || _pauseWork)
			{
				task.Parameters.Dispose(); // this will ensure we don't keep a reference due to callbacks
				return;
			}

			QueueAndGenerateImage(task);
		}
Пример #41
0
		/// <summary>
		/// Schedules the image loading. If image is found in cache then it returns it, otherwise it loads it.
		/// </summary>
		/// <param name="task">Image loading task.</param>
		public async void LoadImage(IImageLoaderTask task)
		{
			Interlocked.Increment(ref _loadCount);

			if (_verbosePerformanceLogging && (_loadCount % 10) == 0)
			{
				LogSchedulerStats();
			}

			if (task == null)
				return;

			if (task.IsCancelled)
			{
				task.Parameters?.Dispose(); // this will ensure we don't keep a reference due to callbacks
				return;
			}

			if (task.Parameters.DelayInMs != null && task.Parameters.DelayInMs > 0)
			{
				await Task.Delay(task.Parameters.DelayInMs.Value).ConfigureAwait(false);
			}

			// If we have the image in memory then it's pointless to schedule the job: just display it straight away
			if (task.CanUseMemoryCache())
			{
				var cacheResult = await task.TryLoadingFromCacheAsync().ConfigureAwait(false);
				if (cacheResult == CacheResult.Found) // If image is loaded from cache there is nothing to do here anymore
				{
					Interlocked.Increment(ref _statsTotalMemoryCacheHits);
				}

				if (cacheResult == CacheResult.Found || cacheResult == CacheResult.ErrorOccured) // if something weird happened with the cache... error callback has already been called, let's just leave
				{
					if (task.Parameters.OnFinish != null)
						task.Parameters.OnFinish(task);
					task.Dispose();
					return;
				}
			}
            else if (task?.Parameters?.Source != ImageSource.Stream && string.IsNullOrWhiteSpace(task?.Parameters?.Path))
			{
				_logger.Debug("ImageService: null path ignored");
				return;
			}

            _dispatch = _dispatch.ContinueWith(async t =>
            {
                try
                {
                    await LoadImageAsync(task).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    _logger.Error("An error occured while loading image", ex);
                }
            });
        }
Пример #42
0
        private async Task LoadImageAsync(IImageLoaderTask task)
        {
            if (task.IsCancelled)
            {
                task.Parameters?.Dispose(); // this will ensure we don't keep a reference due to callbacks
                return;
            }

            if (!task.Parameters.Preload)
            {
                lock (_pendingTasksLock)
                {
                    foreach (var pendingTask in _pendingTasks.ToList()) // FMT: here we need a copy since cancelling will trigger them to be removed, hence collection is modified during enumeration
                    {
                        if (pendingTask.ImageLoadingTask != null && pendingTask.ImageLoadingTask.UsesSameNativeControl(task))
                            pendingTask.ImageLoadingTask.CancelIfNeeded();
                    }
                }
            }

            bool loadedFromCache = await task.PrepareAndTryLoadingFromCacheAsync().ConfigureAwait(false);
            if (loadedFromCache)
            {
                if (task.Parameters.OnFinish != null)
                    task.Parameters.OnFinish(task);

                task.Dispose();
                return; // image successfully loaded from cache
            }

            if (task.IsCancelled || _pauseWork)
            {
                task.Parameters?.Dispose(); // this will ensure we don't keep a reference due to callbacks
                return;
            }

            QueueAndGenerateImage(task);
        }
Пример #43
0
 /// <summary>
 /// Queue an image loading task.
 /// </summary>
 /// <param name="task">Image loading task.</param>
 public static void LoadImage(IImageLoaderTask task)
 {
     Scheduler.LoadImage(task);
 }