/// <summary>
        /// Adds the given <paramref name="task"/> to the list of currently loading tasks.
        /// </summary>
        /// <param name="task"><see cref="IReportProgress"/> to add to the loading list.</param>
        public virtual void ShowLoading(IReportProgress task)
        {
            task.Completed       += OnLoadingTaskCompleted;
            task.ProgressChanged += OnLoadingTaskProgressed;

            IsCompleted = false;

            lock (_loadingReportablesLock)
            {
                RunningProgressReportables.Add(task);
            }

            UpdateLoadingStatus();
        }
        private void CleanupCompletedTasks()
        {
            lock (_loadingReportablesLock)
            {
                foreach (var item in RunningProgressReportables.Where(x => x.IsCompleted).ToList())
                {
                    item.Completed       -= OnLoadingTaskCompleted;
                    item.ProgressChanged -= OnLoadingTaskProgressed;
                    RunningProgressReportables.Remove(item);
                }

                if (RunningProgressReportables.Count == 0)
                {
                    IsCompleted     = true;
                    IsIndeterminate = false;
                    Progress        = 1;
                    Message         = Properties.Resources.UI_Ready;
                    Completed?.Invoke(this, new EventArgs());
                }
            }
        }
        private void UpdateLoadingStatus()
        {
            bool requiresCleanup = false;

            lock (_loadingStatusLock)
            {
                lock (_loadingReportablesLock)
                {
                    // Update progress and determinancy
                    if (RunningProgressReportables.Any(x => x.IsIndeterminate))
                    {
                        IsIndeterminate = true;

                        if (RunningProgressReportables.Count > 1)
                        {
                            Message = Properties.Resources.UI_LoadingGeneric;
                        }
                        else
                        {
                            Message = RunningProgressReportables.First().Message;
                        }
                    }
                    else
                    {
                        IsIndeterminate = false;

                        if (RunningProgressReportables.Count == 1)
                        {
                            Progress = RunningProgressReportables.First().Progress;
                        }
                        else if (RunningProgressReportables.Count == 0)
                        {
                            // Should be unreachable
                            Progress = 0;
                        }
                        else
                        {
                            Progress = RunningProgressReportables.Select(x => x.Progress).Aggregate((x, y) => x * y);
                        }

                        // Update message
                        if (RunningProgressReportables.Count > 1)
                        {
                            Message = Properties.Resources.UI_LoadingGeneric;
                        }
                        else if (RunningProgressReportables.Count == 0)
                        {
                            Message = Properties.Resources.UI_Ready;
                        }
                        else
                        {
                            Message = RunningProgressReportables.First().Message;
                        }
                    }

                    // Cleanup if needed
                    if (RunningProgressReportables.Any(x => x.IsCompleted))
                    {
                        requiresCleanup = true;
                    }
                }
            }

            ProgressChanged?.Invoke(this, new ProgressReportedEventArgs {
                IsIndeterminate = this.IsIndeterminate, Message = this.Message, Progress = this.Progress
            });
            if (requiresCleanup)
            {
                CleanupCompletedTasks();
            }
        }