【问题标题】:How to cancel an existing task being run using Task.Run()?如何取消正在使用 Task.Run() 运行的现有任务?
【发布时间】:2019-10-31 14:24:12
【问题描述】:

下面提到的 UpdateMethod 可以从各种用户操作中调用,例如按钮 UpdateSW1、UpdateSW2、UpdateSW3。

如果用户点击按钮 UpdateSW1,它会暂停任务 10 秒,这里的 waitTime 是 2。现在,当此单击完成时,用户也可以单击 UpdateSW2,当发生这种情况时,我想取消由于第一次单击 (UpdateSW1) 而导致的任务正在进行的延迟或其他操作,并开始 UpdateSW2 的操作。

private void UpdateMethod(int waitTime, int actionNo)
    {
        Task.Run(async () =>
        {
            while (waitTime != 0)
            {
                waitTime--;
                await Task.Delay(5000);
            }
            // DO other stuff ...

            if (actionNO == 1)
            {
                //ops for UpdateSW1
            }
            else
            {
                //ops for UpdateSW2.
            }
        });
    }

更新1:

经过一些试验,我想出了以下代码,现在这在某种程度上可以正常工作,但仍需要改进。如果用户依次单击按钮 UpdateSW1 和 UpdateSW2 ,然后单击取消按钮,它会取消其中一个任务(由于 UpdateSW1 click 正在运行)但不取消另一个任务(其中一个由于单击 updteSW2 正在运行)我希望取消这两个任务。如何做到这一点。

修改方法:

private CancellationTokenSource cts; // declared as class variable. 

private void UpdateMethod(int waitTime, int actionNo)
    {
        cts = new CancellationTokenSource();
        CancellationToken token1 = cts.Token;
        try
        {
            Task.Run(async () =>
            {
                while (waitTime != 0)
                {
                    waitTime--;
                    await Task.Run(() => Task.Delay(5000, token1), token1);
                    token1.ThrowIfCancellationRequested();
                }
                // DO other stuff ...

                if (actionNO == 1)
                {
                    //ops for UpdateSW1
                }
                else
                {
                    //ops for UpdateSW2.
                }
            }, token1);
        }
        catch (OperationCanceledException e)
        {
            // update DB log
        }
    }

【问题讨论】:

  • 取消意味着取消,而不是暂停或取消暂停。带信号的取消令牌意味着整个UpdateMethod 应该尽快停止。如果您想在继续之前等待某些用户输入或其他事件,请使用由 click 事件处理程序发出信号的 TaskCompletionSource。如果你想把它和超时结合起来,你可以使用await Task.WhenAny(taskFromSource,Task.Delay(10000));
  • 对不起,我想我应该更清楚地表达我的问题。我的基本意思是,一旦调用 updateMethod,它基本上会在任何操作开始之前等待一段时间(取决于参数 waitTime)。现在在这段等待或等待后的操作执行期间,用户可以点击UpdateSW2,如果发生这种情况,我希望取消当前正在进行的任务并重新开始。我可以研究关于信号取消令牌的任何样本或文章吗?不幸的是,我对此进行了谷歌搜索,无法理解或找到一个简单的示例。
  • 我认为你的 catch 块在方法之外不正确。

标签: c# task


【解决方案1】:

整个等待循环

            while (waitTime != 0)
            {
                waitTime--;
                await Task.Run(() => Task.Delay(5000, token1), token1);
                token1.ThrowIfCancellationRequested();
            }

可以简化为

await Task.Delay(waitTime, token1);

当令牌发出信号时,延迟将结束。无需绕道而行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-12
    • 2015-08-05
    • 1970-01-01
    相关资源
    最近更新 更多