/// <summary> /// Enables progress polling. /// Use <see cref="CurrentProgress"/> to retrieve the task's current progress. /// Returns the current progress task, so that methods may be chained. /// </summary> public ProgressTask EnablePolling(int maximumDepth) { this.pollingEnabled = true; this.currentProgressAccessed = true; this.currentProgress = new ProgressChangedInfo(new ProgressInfo(0f, null, null), null); this.maximumDepth = (ProgressDepth)maximumDepth; return(this); }
/// <summary> /// Calculates the current progress, /// and invokes the callback for the /// current task and all parent tasks. /// </summary> private void OnProgressChanged(object currentStepArg) { // First, an optimization: // we might not need to calculate progress at all, // if no one is listening: ProgressDepth depth = 0; var task = this; while (true) { // Determine if we've reached the bottom of the stack or the maximum depth: if (task == null || task.maximumDepth < depth) { // No one's listening this deep! // Skip calculations. return; } // Check for a callback: if (task.progressChangedCallback != null) { break; } // Check for polling: if (task.pollingEnabled) { if (task.currentProgressAccessed || (int)depth < task.currentProgress.CurrentDepth) { // Polling is enabled and is ready for a new CurrentProgress. break; } } // Traverse the progress stack: depth++; task = task.parent; } depth = 0; task = this; var taskProgress = 0.0f; var allProgress = new Stack <ProgressInfo>(); while (true) { // Calculate the task's progress: if (task.isEnded) // 100%! { taskProgress = 1.0f; } else { taskProgress = task.calculator.CalculateProgress(taskProgress); } allProgress.Push(new ProgressInfo(taskProgress, task.taskKey, task.taskArg)); // Raise events or update Polling: ProgressChangedInfo progressChangedInfo = null; // Raise the event if necessary: if (task.progressChangedCallback != null) { progressChangedInfo = new ProgressChangedInfo(allProgress, currentStepArg); task.progressChangedCallback(progressChangedInfo); } // Update the CurrentProgress so that it can be used for polling. if (task.pollingEnabled) { // If the current CurrentProgress hasn't been accessed, // then we will only update if the new item is higher priority (lower depth): if (task.currentProgressAccessed || (int)depth < task.currentProgress.CurrentDepth) { if (progressChangedInfo == null) { progressChangedInfo = new ProgressChangedInfo(allProgress, currentStepArg); } task.currentProgressAccessed = false; task.currentProgress = progressChangedInfo; } } // Traverse the progress stack: depth++; task = task.parent; // Determine if we've reached the bottom of the stack or the maximum depth: if (task == null || task.maximumDepth < depth) { break; } } }