在另一个事件处理方法中取消已经初始化和运行的任务

Cancel tasks that have been initialized and run in another event handler method

我正在构建一个 C#/Windows 表单应用程序。

在表单上各种按钮的点击事件处理程序中,我初始化并触发了不同的任务。但是,对于某些按钮单击,我想取消任何仍然 运行 由某些其他单击事件处理程序启动的任务。

下面是我的代码。到目前为止,第二个版本是我尝试使用第二种方法来取消第一种方法启动的 运行 任务,但是它还不起作用。如何取消 运行 任务?

示例代码(尚未添加取消令牌):

private void btnFrontDoorCycle_Click(object sender, EventArgs e)
{
    Task.Factory.StartNew(() =>
    {
        // Do function 1
        // Do function 2
        // etc
    });
}

private void btnFrontDoorClose_Click(object sender, EventArgs e)
{
    // If task started in btnFrontDoorCycle_Click is running, cancel it here
    Task.Factory.StartNew(() =>
    {
        // Do function 5
        // Do function 6
        // etc
    });
}

示例代码(我尝试添加取消令牌时无法正常工作):

private CancellationTokenSource cancellationTokenSource;
private void btnFrontDoorCycle_Click(object sender, EventArgs e)
{
    Task.Factory.StartNew(() =>
    {
        // Do function 1
        // Do function 2
        // etc
    }, cancellationToken);
}

private void btnFrontDoorClose_Click(object sender, EventArgs e)
{
    // If task started in btnFrontDoorCycle_Click is running, cancel it here
    if (this.cancellationTokenSource != null)
    {
        this.cancellationTokenSource.Cancel();
    }
    this.cancellationTokenSource = new CancellationTokenSource();
    CancellationToken cancellationToken = this.cancellationTokenSource.Token;
    Task.Factory.StartNew(() =>
    {
        // Do function 5
        // Do function 6
        // etc
    });
}

您是否在代码中检查 cancellationToken.IsCancelationRequested? 我认为这就是问题所在。

应该是这样的:

// Do function 1
if (token.IsCancellationRequested)
{
    return;
}
// Do function 2
// Were we already canceled?
ct.ThrowIfCancellationRequested();// another variant
// etc

更多详情:https://msdn.microsoft.com/en-us//library/dd997396(v=vs.110).aspx

您需要检查令牌是否已被取消。下面是我编写的一小段代码,只是为了检查它是如何工作的。希望你能从中提取你需要的东西...

internal class TaskCancellationProblem
{
    private CancellationTokenSource tokenSource;
    private CancellationToken token;

    public TaskCancellationProblem()
    {
        ResetSourceAndToken();
    }

    private void ResetSourceAndToken()
    {
        tokenSource = new CancellationTokenSource();
        token = tokenSource.Token;
    }

    public void RunFirstTask()
    {
        // check if cancellation has been requested previously and reset as required
        if (tokenSource.IsCancellationRequested)
            ResetSourceAndToken();

        Task.Factory.StartNew(() =>
        {
            while (!token.IsCancellationRequested)
            {
                Console.WriteLine("Doing first task");
                Thread.Sleep(1000);
            }
        }, token);
    }

    public void CancelFirstAndRunSecond()
    {
        // Cancel the task that was running
        tokenSource.Cancel();
        Task.Factory.StartNew(() =>
        {
            while (true)
            {
                Console.WriteLine("Doing second task");
                Thread.Sleep(1000);
            }
        });
    }
}