我已经实现了在后台运行繁重任务的辅助方法
它接受多个代表并且不阻塞:
- 异步部分
- 成功部分(GUI)
- 异步部分失败(GUI)
- 最后(GUI)(可选)
每个 gui 部分都可以开始它自己的序列,即发生对我的辅助方法的递归调用。但是我想在附加任务完成时将任何部分视为已完成。
这张图片解释了我的意思:
为了提供这种条件,我将我的异步任务创建为附加到父级,这给了我需要的东西。
我唯一的问题是,在 TPL for .NET v4DenyChildAttach
选项中不存在,所以当我的方法在其他任务中被调用时,它会附加到这个任务。
我将创建一个带有参数的重载来指示附加的需要,但是我想要以下默认行为:
如果递归调用,则附加,否则除非明确说明,否则不要附加。
明确地说,我应该设置一些指示递归的上下文,但不明白如何......
PS Now 方法看起来像这样(对于 Action、Func 有很多重载):
public static CancellationTokenSource ExecuteBlockingOperation(Action action,
Action completition,
Action<AggregateException> onException,
Action<bool, bool, bool> @finally = null)
{
if (action == null)
throw new ArgumentNullException("action");
if (completition == null)
throw new ArgumentNullException("completition");
if (onException == null)
throw new ArgumentNullException("onException");
var cts = new CancellationTokenSource();
var token = cts.Token;
var scheduler = SynchronizationContext.Current == null? TaskScheduler.Default : TaskScheduler.FromCurrentSynchronizationContext();
var successfullyCompleted = false;
var task = new Task(action, TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent);
var onFault = task.ContinueWith(asyncPartTask => onException(asyncPartTask.Exception),
CancellationToken.None,
TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent,
scheduler);
var onSuccess = task.ContinueWith(asyncPart =>
{
if (!token.IsCancellationRequested)
{
completition();
successfullyCompleted = true;
}
}, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.AttachedToParent, scheduler);
if (@finally != null)
{
Task.Factory.ContinueWhenAll(new[] { onSuccess, onFault },
tasks =>
{
var isSuccess = task.Status == TaskStatus.RanToCompletion;
@finally(isSuccess, token.IsCancellationRequested, successfullyCompleted);
},
CancellationToken.None,
TaskContinuationOptions.AttachedToParent, scheduler);
}
task.Start();
return cts;
}