Exemple #1
0
        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.Debug("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);
                }
            });
        }
        /// <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 void LoadImage(IImageLoaderTask task)
        {
            if (task == null)
            {
                return;
            }

                        #pragma warning disable 4014
            Task.Run(async() =>
            {
                if (task.Parameters.DelayInMs != null && task.Parameters.DelayInMs > 0)
                {
                    await Task.Delay(task.Parameters.DelayInMs.Value).ConfigureAwait(false);
                }

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

                if (!task.Parameters.Preload)
                {
                    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 = 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);
            });
                        #pragma warning restore 4014
        }
Exemple #3
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);
            }
        }
        /// <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);
        }
Exemple #5
0
        protected async Task RunImageLoadingTaskAsync(IImageLoaderTask pendingTask)
        {
            var keyRaw = pendingTask.KeyRaw;

            try
            {
                if (Configuration.VerbosePerformanceLogging)
                {
                    LogSchedulerStats();
                    Stopwatch stopwatch = Stopwatch.StartNew();

                    await pendingTask.RunAsync().ConfigureAwait(false);

                    stopwatch.Stop();

                    Logger.Debug(string.Format("[PERFORMANCE] RunAsync - NetManagedThreadId: {0}, NativeThreadId: {1}, Execution: {2} ms, Key: {3}",
                                               Performance.GetCurrentManagedThreadId(),
                                               Performance.GetCurrentSystemThreadId(),
                                               stopwatch.Elapsed.Milliseconds,
                                               pendingTask.Key));
                }
                else
                {
                    await pendingTask.RunAsync().ConfigureAwait(false);
                }
            }
            finally
            {
                lock (_runningTasksLock)
                {
                    RunningTasks.Remove(keyRaw);

                    lock (_similarTasksLock)
                    {
                        if (SimilarTasks.Count > 0)
                        {
                            SimilarTasks.RemoveAll(v => v == null || v.IsCompleted || v.IsCancelled);
                            var similarItems = SimilarTasks.Where(v => v.KeyRaw == keyRaw).ToList();
                            foreach (var similar in similarItems)
                            {
                                SimilarTasks.Remove(similar);
                                LoadImage(similar);
                            }
                        }
                    }
                }

                pendingTask?.Dispose();
                await TakeFromPendingTasksAndRunAsync().ConfigureAwait(false);
            }
        }
Exemple #6
0
 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();
     }
 }
        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);
        }
        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)
            {
                foreach (var pendingTask in _pendingTasks)
                {
                    if (pendingTask.Value.ImageLoadingTask != null && pendingTask.Value.ImageLoadingTask.UsesSameNativeControl(task))
                    {
                        pendingTask.Value.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);
            return;
        }
		/// <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);
		}
        protected void QueueImageLoadingTask(IImageLoaderTask task)
        {
            if (task.IsCancelled || task.IsCompleted || ExitTasksEarly)
            {
                if (!task.IsCompleted)
                {
                    task?.Dispose();
                }

                return;
            }

            IImageLoaderTask similarRunningTask = null;

            if (!task.Parameters.Preload)
            {
                PendingTasks.CancelWhenUsesSameNativeControl(task);
            }

            similarRunningTask = PendingTasks.FirstOrDefaultByRawKey(task.KeyRaw);
            if (similarRunningTask == null)
            {
                Interlocked.Increment(ref _statsTotalPending);
                Enqueue(task);
            }
            else
            {
                if (task.Parameters.Priority.HasValue && (!similarRunningTask.Parameters.Priority.HasValue ||
                                                          task.Parameters.Priority.Value > similarRunningTask.Parameters.Priority.Value))
                {
                    similarRunningTask.Parameters.WithPriority(task.Parameters.Priority.Value);
                    PendingTasks.UpdatePriority(similarRunningTask, task.Parameters.Priority.Value);
                }

                if (task.Parameters.OnDownloadProgress != null)
                {
                    var similarTaskOnDownloadProgress = similarRunningTask.Parameters.OnDownloadProgress;
                    similarRunningTask.Parameters.DownloadProgress((DownloadProgress obj) =>
                    {
                        similarTaskOnDownloadProgress?.Invoke(obj);
                        task.Parameters.OnDownloadProgress(obj);
                    });
                }
            }

            if (PauseWork)
            {
                return;
            }

            if (similarRunningTask == null || !task.CanUseMemoryCache)
            {
                TakeFromPendingTasksAndRun();
            }
            else
            {
                Interlocked.Increment(ref _statsTotalWaiting);
                Logger.Debug(string.Format("Wait for similar request for key: {0}", task.Key));
                SimilarTasks.Add(task);
            }
        }
        /// <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);
                }
            });
        }
Exemple #12
0
        protected void QueueImageLoadingTask(IImageLoaderTask task)
        {
            var 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 if (similarRunningTask.ImageLoadingTask != null)
                {
                    if (task.Parameters.Priority.HasValue &&
                        (!similarRunningTask.ImageLoadingTask.Parameters.Priority.HasValue
                         ||
                         (task.Parameters.Priority.Value > similarRunningTask.ImageLoadingTask.Parameters.Priority.Value)))
                        similarRunningTask.ImageLoadingTask.Parameters.WithPriority(task.Parameters.Priority.Value);

                    if (task.Parameters.OnDownloadProgress != null)
                    {
                        var similarTaskOnDownloadProgress =
                            similarRunningTask.ImageLoadingTask.Parameters.OnDownloadProgress;

                        similarRunningTask.ImageLoadingTask.Parameters.DownloadProgress(obj =>
                        {
                            similarTaskOnDownloadProgress?.Invoke(obj);
                            task.Parameters.OnDownloadProgress(obj);
                        });
                    }
                }
            }

            if (PauseWork)
                return;

            if ((similarRunningTask == null) || !currentPendingTask.ImageLoadingTask.CanUseMemoryCache)
                TakeFromPendingTasksAndRun();
            else
                WaitForSimilarTaskFinished(currentPendingTask, similarRunningTask);
        }
        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);
        }
		/// <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);
                }
            });
        }
Exemple #15
0
        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.Debug("ImageService: null path ignored");
                task?.Dispose();
                return;
            }

            if (task == null)
            {
                return;
            }

            if (task.IsCancelled || task.IsCompleted)
            {
                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
                {
                    EvictStaleTasks();

                    if (task.IsCancelled || task.IsCompleted)
                    {
                        task?.Dispose();
                        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();
                                }
                            }
                        }
                    }

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

                    QueueImageLoadingTask(task);
                }
                catch (Exception ex)
                {
                    Logger.Error(string.Format("Image loaded failed: {0}", task?.Key), ex);
                }
            });
        }