只需要'最近'任务 - 取消/忽略最佳做法? [英] Only need 'most recent' Task - best practices for cancelling/ignoring?

查看:208
本文介绍了只需要'最近'任务 - 取消/忽略最佳做法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a task that looks like this:

var task = Task.Factory.StartNew <object>(LongMethod);
task.ContinueWith(TaskCallback, TaskScheduler.FromCurrentSynchronizationContext());



LongMethod调用长时间运行的服务,在此期间,我不能(或至少不想我可以),不断地轮询取消标记,看它是否已被取消。不过,我感兴趣的是取消,或忽略,回调方法。

LongMethod calls a long running service, during which I can’t (or at least, don’t think I can), constantly poll a cancellation token to see if it has been cancelled. However, I am interested in ‘cancelling’, or ignoring, the callback method.

当TaskCallback叫,我只在结果感兴趣的如果的它是从最近的任务(让我们假设该LongMethod调用服务保持秩序,还假设用户可以点击按钮无数次,但只有最近的一次是相关的)。

When the TaskCallback is called, I am only interested in the ‘result’ if it is the from the most recent task (let us assume that the service that LongMethod calls preserves order, and also assume that the user can click the button numerous times, but only the latest one is relevant).

我已修改了以下列方式代码:创建任务后,我将它添加到堆栈的顶部。在TaskCallback,我检查,看看是否已经传递给回调任务是最新的一个(即在堆栈的顶部的TryPeek)。如果不是这样,我只是忽略的结果。

I have modified my code in the following way: after a task is created, I add it to the top of a stack. In the TaskCallback, I check to see if the task that has been passed to the callback is the most recent one (i.e. a TryPeek at the top of the stack). If it is not, I just ignore the result.

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
}



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

I am quite certain that this isn’t a ‘best practices’ solution. But what is? Passing and maintaing cancellation tokens doesn’t really seem all that elegant, either.

推荐答案

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

I personally find the following approach to be the most elegant:

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

这篇关于只需要'最近'任务 - 取消/忽略最佳做法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆