예제 #1
0
        public async void ShowProgressWindow(WorkProgressViewModel workProgress, int minDelay)
        {
            if (workProgress == null)
            {
                throw new ArgumentNullException(nameof(workProgress));
            }
            // Tell the work progress view model that a window will be open for it
            workProgress.NotifyWindowWillOpen();

            // Create a container object for the work progress to put it in the queue
            var progress = new PendingWorkProgress(workProgress);

            // As soon as the work is finished, we should display the window, even if the delay is not complete
            workProgress.WorkFinished += (sender, e) => progress.ReadyToDisplay.TrySetResult(0);
            if (workProgress.WorkDone)
            {
                progress.ReadyToDisplay.TrySetResult(0);
            }

            // Compute the list of progress window that should be displayed before this one
            List <PendingWorkProgress> precedingWindows;

            lock (pendingProgressWindows)
            {
                precedingWindows = new List <PendingWorkProgress>(pendingProgressWindows);
                pendingProgressWindows.Add(progress);
            }
            // Enqueue a task to display the window when it's ready.
            DisplayProgressWindow(precedingWindows, progress);

            // Wait the delay before notifying that we're ready to display
            await Task.Delay(minDelay);

            progress.ReadyToDisplay.TrySetResult(0);
        }
예제 #2
0
        private async void DisplayProgressWindow(List <PendingWorkProgress> precedingWindows, PendingWorkProgress nextWindow)
        {
            // Wait for all preceding windows to be displayed first
            await Task.WhenAll(precedingWindows.Select(x => x.Displayed.Task));

            // Then wait for the next window to be ready to display
            await nextWindow.ReadyToDisplay.Task;

            // Check if we should actually display the window
            if (!nextWindow.WorkProgress.WorkDone || nextWindow.WorkProgress.ShouldStayOpen())
            {
                await nextWindow.WorkProgress.Dispatcher.InvokeAsync(() =>
                {
                    var progressWindow = new WorkProgressWindow(nextWindow.WorkProgress);

                    // Remove this window from the list of pending window
                    lock (pendingProgressWindows)
                    {
                        pendingProgressWindows.Remove(nextWindow);
                    }

                    try
                    {
                        // Notify in the next frame that the window has been displayed
                        nextWindow.WorkProgress.Dispatcher.InvokeAsync(() => nextWindow.Displayed.SetResult(0));
                        WindowManager.ShowBlockingWindow(progressWindow);
                    }
                    catch (Exception e)
                    {
                        // On Windows 8, an exception might occur in the System.Windows.Shell.WindowChromeWorker class
                        // if the progress window is closed programmatically, apparently if this happens too early after
                        // loading it. Let's ignore the exception for the moment, as a workaround.
                        e.Ignore();
                    }
                });
            }
            else
            {
                // Remove this window from the list of pending window
                lock (pendingProgressWindows)
                {
                    pendingProgressWindows.Remove(nextWindow);
                }
                // Notify that the window should be considered as displayed.
                nextWindow.Displayed.SetResult(0);
            }

            nextWindow.WorkProgress.NotifyWindowClosed();
        }