只需要“最近”任务 - 取消/忽略最佳做法?(Only need 'most recent&

2019-07-30 02:24发布

我有一个看起来像这样的任务:

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
}

我敢肯定,这不是一个“最佳做法”的解决方案。 但究竟是什么? 传递和维修器材取消标记并没有真正似乎所有的优雅,无论是。

Answer 1:

我个人觉得下面的方法是最优雅:

// 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
}


Answer 2:

我明白,你无法取消长期运行的任务,但希望的过程中从用户的角度看被立即中止时,他取消。

与你的长期运行的任务开始并行取消任务。 继续关闭的Task.WhenAny(longRunningTask, cancelTask)和检查,如果完成的任务是长期运行的任务或取消任务。 然后,您可以决定做什么(显示结果或更新UI)。

当您取消“取消任务”的延续会立即触发。



文章来源: Only need 'most recent' Task - best practices for cancelling/ignoring?