我有一个看起来像这样的任务:
var task = Task.Factory.StartNew <object>(LongMethod);
task.ContinueWith(TaskCallback, TaskScheduler.FromCurrentSynchronizationContext());
LongMethod调用长时间运行的服务,在此期间,我不能(或至少不认为我可以),不断查询一个取消标记,看它是否已被取消。 不过,我很感兴趣,“取消”,或忽略,回调方法。
当TaskCallback叫,我只在“结果”有兴趣,如果它是从最近的任务(让我们假设该LongMethod通话服务保持秩序,还假设用户可以点击按钮无数次,但只有最近的一次是相关的)。
我已经修改我通过以下方式代码:创建任务后,我将它添加到堆栈的顶部。 在TaskCallback,我查看是否已传递给回调的任务是最近的一次(即TryPeek在堆栈的顶部)。 如果不是,我只是忽略的结果。
private ConcurrentStack<Task> _stack = new ConcurrentStack<Task>();
private void OnClick(object sender, ItemClickEventArgs e)
{
var task = Task.Factory.StartNew < object >( LongMethod);
task.ContinueWith(TaskCallback, TaskScheduler.FromCurrentSynchronizationContext());
_stack.Push(task);
}
private void TaskCallback(Task<object> task)
{
Task topOfStack;
if(_stack.TryPeek(out topOfStack)) //not the most recent
{
if (task != topOfStack) return;
}
//else update UI
}
我敢肯定,这不是一个“最佳做法”的解决方案。 但究竟是什么? 传递和维修器材取消标记并没有真正似乎所有的优雅,无论是。
我个人觉得下面的方法是最优雅:
// Cancellation token for the latest task.
private CancellationTokenSource cancellationTokenSource;
private void OnClick(object sender, ItemClickEventArgs e)
{
// If a cancellation token already exists (for a previous task),
// cancel it.
if (this.cancellationTokenSource != null)
this.cancellationTokenSource.Cancel();
// Create a new cancellation token for the new task.
this.cancellationTokenSource = new CancellationTokenSource();
CancellationToken cancellationToken = this.cancellationTokenSource.Token;
// Start the new task.
var task = Task.Factory.StartNew<object>(LongMethod, cancellationToken);
// Set the task continuation to execute on UI thread,
// but only if the associated cancellation token
// has not been cancelled.
task.ContinueWith(TaskCallback,
cancellationToken,
TaskContinuationOptions.NotOnCanceled,
TaskScheduler.FromCurrentSynchronizationContext());
}
private void TaskCallback(Task<object> task)
{
// Just update UI
}
我明白,你无法取消长期运行的任务,但希望的过程中从用户的角度看被立即中止时,他取消。
与你的长期运行的任务开始并行取消任务。 继续关闭的Task.WhenAny(longRunningTask, cancelTask)
和检查,如果完成的任务是长期运行的任务或取消任务。 然后,您可以决定做什么(显示结果或更新UI)。
当您取消“取消任务”的延续会立即触发。