【问题标题】:Cancel Async task if running and run it again (sort of refresh behaviour)如果正在运行,请取消异步任务并再次运行它(刷新行为)
【发布时间】:2020-01-07 19:30:26
【问题描述】:

我有一个包含两个DataGridView 控件的表单,每个控件都有一个刷新按钮。控件从两种方法(task1 和 task2)获取数据。还有一个通用刷新按钮可以重新填充这两个控件。 填充控件的两种方法不能同时运行并且很耗时(每个大约 1 分钟),因此我希望它们在后台运行以保持表单处于活动状态。 当我按下每个刷新按钮时,我想取消当前正在进行的任何活动任务并重新开始。

另外,我已经实现了一个进度条来填充每个方法。

到目前为止,我已经写了这段代码:

  • 注意:编写任务仅用于测试使用async-awaitTask.Run 的逻辑

public bool pending = false; // I have used a public boolean to determine if the tasks are in progress.

private async void Button1_Click(object sender, EventArgs e) 
{
    var progress = new Progress<int>(value => { toolStripProgressBar1.Value = value; });
    string test2 = "";
    string test1 = "";
    CancellationTokenSource source = new CancellationTokenSource();
    if (pending)
    {source.Cancel();}
    pending = true;
    await Task.Run(() =>
    {
    test1 = task1(progress, source.Token);
    });

    toolStripProgressBar1.Value = 0;
    await Task.Run(() =>
    {
    test2 = task2(progress, source.Token);                
    });
    pending = false;
    toolStripProgressBar1.Value = 0;
}

private string task1(IProgress<int> progress, CancellationToken token)
{
    if (token.IsCancellationRequested)
    {
    return "cancelled";
    }
    for (int i = 0; i != 100; ++i)
    {
        if (progress != null)
             progress.Report(i);
        Thread.Sleep(100);
        Console.WriteLine(i.ToString() + ";");
        if (token.IsCancellationRequested)
        {
        return "cancelled";
        }
    }
    return "task1";
}

private string task2(IProgress<int> progress, CancellationToken token)
{

    if (token.IsCancellationRequested)
    {
    return "cancelled";
    }
    for (int i = 0; i != 100; ++i)
    {
        if (progress != null)
            progress.Report(i);
        Thread.Sleep(100);
         Console.WriteLine(i.ToString() + ";");
        if (token.IsCancellationRequested)
        {
        return "cancelled";
        }
    }
    return "task2";
}
  • 注意:Button_1 控件是一个接一个地运行这两种方法的通用刷新按钮。 Button_2 和 Button_3 Click 事件代码类似于 Button_1 Click 事件,但它只运行一个任务,而不是同时运行两个任务。为了保持代码干净,我没有把它们放在这里。

使用此代码,我得到以下行为。

  • 第一次单击 Button_1 - 代码运行正常,进度条运行正常且完全。

  • 在进度条完成之前第二次单击 Button_1(bool 挂起为真) - 进度条重新启动但立即恢复到初始进度并且初始计数仍在运行,不会被 if (token.IsCancellationRequested) 取消

  • 在进度条完成之前第三次单击 Button_1 - 进度条开始闪烁,初始计数仍在运行,另一个计数开始。

我知道代码不完整,因为我没有找到在方法被取消后重新启动它们的方法。

分析到目前为止我是如何编写代码的,我不明白进度条的行为。另外,我不明白为什么当我第二次单击按钮时第一个计数仍在运行。 在再次调用它们之前取消任何正在运行的任务的最佳方法是什么?

【问题讨论】:

    标签: c# async-await task


    【解决方案1】:

    每次单击按钮时,取消标记都会重新初始化。

    source = new CancellationTokenSource();

    我怀疑这会干扰实现行为。 之前的“Task1”任务继续运行,而新的“Task1”任务被取消。

    当“Task2”运行时,这更进一步,有两个任务正在执行。 这会导致进度条闪烁,因为每个任务都会在进度条上更新自己的值。

    一旦启动取消,您应该在重新启动新任务之前等待。

    【讨论】:

      猜你喜欢
      • 2015-08-05
      • 1970-01-01
      • 1970-01-01
      • 2012-06-03
      • 1970-01-01
      • 2016-01-14
      • 2014-12-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多