使用取消令牌取消多个任务

Use a cancellation Token to cancel multiple Tasks

我想知道如何取消任务。已经读过一些这样的文章:https://docs.microsoft.com/en-us/dotnet/standard/threading/cancellation-in-managed-threads?redirectedfrom=MSDN

但是我已经完成了任务,想知道如何让它们可取消。

要么一次全部完成,如果不可能,则应取消一个任务,然后他应取消下一个任务,直到全部完成。

EDIT CancellationToken 的使用是否正确? 任务按照我的意愿继续 运行,但是当我按下取消按钮时,出现错误。如果我启动我发布的版本,应用程序就会关闭:* enter image description here

 void btnPause_Click(object sender, EventArgs e)
        {

            cts.Cancel();

        }
   

       async void btnStart_Click(object sender, EventArgs e)
    {
        try
        {
            cts = new CancellationTokenSource();
            var token = cts.Token;
            var t1 = Task.Run(() => START(token));
            await Task.WhenAny(new[] { t1 });
        }
        catch (OperationCanceledException)
        {
            // Handle canceled
        }
        catch (Exception)
        {
            // Handle other exceptions
        }
    }
    ///////////////////////////////////////////
    async void START(CancellationToken token)
    {
        for (int i = 0; i < 1; i++)
        {
            token.ThrowIfCancellationRequested();
            await Task.Delay(100, token);
             try { 
              
                    if()
                    {
                        
                    }

            }catch { }  
        }
        Thread.Sleep(2000);
        var t2 = Task.Run(() => START2(token));
        await Task.WhenAny(new[] { t2});
    }
    ///////////////////////////////////////////////
   async void START2(CancellationToken token)
    {
       
        for (int i = 0; i < 10; i++)
        {
            token.ThrowIfCancellationRequested();
            await Task.Delay(100, token);
             try { 
              
                    if()
                    {
                        
                    }

            }catch { }  
        }
        Thread.Sleep(7000);


        var t3 = Task.Run(() => MOVE(token));
        await Task.WhenAny(new[] {t3});
    }
    //////////////////////////////////////////
   async void MOVE(CancellationToken token)
    {


        for (int i = 0; i < 3; i++)
        {

            token.ThrowIfCancellationRequested();
            await Task.Delay(100, token);
            try { 
              
                    if()
                    {

                    }

            }catch { }

        }
        var t4 = Task.Run(() => MOVE2(token));
        await Task.WhenAny(new[] {t4 });

    }

在稍微简化的示例中使用 CancellationTokenSource:

CancellationTokenSource cts = new CancellationTokenSource();
async void Cancel_Click(object sender, EventArgs e)
{
    cts.Cancel();
}
async void btnStart_Click(object sender, EventArgs e)
{
    try{
       cts = new CancellationTokenSource();
       var token = cts.Token;
       var t1 = Task.Run(() => Start(token));
       var t2 = Task.Run(() => Start(token));
       await Task.WhenAny(new []{t1, t2});
    }
    catch(OperationCancelledException){
        // Handle canceled
    }
    catch(Exception){
        // Handle other exceptions
    }
}

void Start(CancellationToken token)
{
    for (int i = 0; i < 100; i++)
    {
         token.ThrowIfCancellationRequested();
         // Do work 
         Thread.Sleep(100);
    }
}

单击该按钮时,它将首先创建一个新的 cancellationTokenSource,然后在后台线程上启动两个任务,这两个任务都使用来自新创建的令牌源的令牌。当按下 cancelButton 时,令牌将设置为 canceled-state,下次每个后台线程调用 ThrowIfCancellationRequested 时,它们将抛出异常。这会将任务放入 canceled-state,等待这将抛出需要捕获的 operationCancelledException。请注意,当等待多个任务时,您可能会得到一个 aggregateException,它包装了多个异常并需要解包。