简体   繁体   中英

Cancel Async task if running and run it again (sort of refresh behaviour)

I have a form containing two DataGridView controls, each one of them having a Refresh button. The controls get data from two methods (task1 and task2). There is also a general refresh button that repopulates both controls. The two methods that populate the controls cannot run simultaneously and are time consuming (aprox. 1 minute each), thus I want them to run in background in order to keep the form active. When I press each of the refresh buttons, I want to cancel any active task if it is currently in progress and start again.

Also, I have implemented a progress bar that fills for each method.

So far, I have written this code:

  • Note: the tasks are written only for testing the logic for using async - await and Task.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";
}
  • Note: Button_1 control is the general refresh button that run both methods, one after the other. Button_2 and Button_3 Click event codes are similar to Button_1 Click event, but it runs only one task, not both. In order to keep the code clean, I did not put them here.

Using this code I get the following behaviour.

  • First click of Button_1 - the code runs ok and the progressbar runs ok and completely.

  • Second click of Button_1 before the progressbar is complete (bool pending is true) - the progressbar restarts but imediattely resumes to the initial progress and the initial count is still running, not being canceled by the if (token.IsCancellationRequested)

  • Third click of Button_1 before the progressbar is complete - the progressbar begins to flicker, the initial count is still running and another count starts.

I know the code is incomplete because I didn't find a way to restart the methods once they are cancelled.

Analyzing how I have written the code so far, I don't understand the progressbar behaviour. Also, I don't understand why the first count is still running when I click the button for the second time. What is the best approach for cancelling any running tasks before calling them again?

Every time you click the button, the Cancellation token is reinitialized.

source = new CancellationTokenSource();

I suspect this is messing with the implementation behavior. The previous 'Task1' task keeps running whereas the new 'Task1' task is cancelled.

This goes further when 'Task2' is running, there are two tasks executing. This leads to flickering of the progress bar as each task updates its own value on progress bar.

Once cancellation is initiated, you should wait before re-initiating the new tasks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM