试图理解try / catch(AggregateException)不会取消我的任务。 [英] Trying to understand try/catch( AggregateException ) does not cancel my task.

查看:71
本文介绍了试图理解try / catch(AggregateException)不会取消我的任务。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正试图加强任务和所有这些。我想尝试取消任务。在 UpdateText
里面,如果我不使用try catch,我的取消就会发生。但是,如果我在for循环内部或外部放置了try函数,我的取消不会被触发。 我甚至在catch块中设置了一个断点来查看它是否被捕获,但它不是
。 在我的表单上,我有两个按钮,一个用于开始执行,一个用于取消。 

I'm trying to ramp up on Tasks and all that. I wanted to experiment with canceling a task. Inside UpdateText if i DO NOT use a try catch my cancel happens. However, if I put a try catch in the function, either inside or outside the for loop, my cancel is not being triggered.  I even put a break point in catch block to see if it's being caught, but it's not.  On my form, I have two buttons, one to start execution, one to cancel. 

执行的条目是  RunningTwoTasksContinuationwhich
获取按下按钮点击。

The entry into execution is RunningTwoTasksContinuationwhich gets called on a button click.

        CancellationTokenSource cts;

       的CancellationToken        ct;

        CancellationTokenSource cts;
        CancellationToken       ct;

        public Form1()

        {

            InitializeComponent();



            cts = new CancellationTokenSource();

            ct = cts.Token;

        }

        public Form1( )
        {
            InitializeComponent( );

            cts = new CancellationTokenSource( );
            ct = cts.Token;
        }

        private void btnCancel_Click(object sender,EventArgs e)

        {

            cts.Cancel();

        }

        private void btnCancel_Click( object sender, EventArgs e )
        {
            cts.Cancel( );
        }

推荐答案

您的代码存在一些问题。首先,您只在首次启动任务时检查取消。你应该每次检查取消。

There's some problems with your code. Firstly you are only checking for cancellation when the task first starts. You should be checking for cancellation each time through.

private void UpdateText ( object state )
{            
    for (int i = 0; i < 500; i++)
    {
        if (ct.IsCancellationRequested)
        {
            richTextBox1.Invoke(new Action(() => richTextBox1.Text += "\n" + " ====== CANCELED ====== "));
            ct.ThrowIfCancellationRequested();
        };

        richTextBox1.Invoke(new Action(() => richTextBox1.Text += "\n" + state + " " + i));
    }
}

通过任务本身处理取消通常是一个坏主意。取消是外部呼叫者通知任务完成。因此,呼叫者(等待任务的人)处理取消。在你的情况下,如果try-catch实际上
工作,那么任务就不会被取消,因为你正在默默地吃异常。 

It is generally a bad idea to handle cancellation with the task itself. Cancellation is the external caller notifying the task to complete. Therefore the caller (the person waiting on the task) handles the cancellation. In your case, had the try-catch actually worked, the task wouldn't have cancelled because you are silently eating the exception. 

ThrowIfCancellationRequested会抛出OperationCanceledException。这会导致调用函数抛出,这使您无法完成任务。任务类处理此异常(以及其他异常)并将它们包装成AggregateException但
是调用者而不是任务。如果您修改了catch以使用OperationCanceledException,则会看到它被调用。但正如我已经说过你的任务不会被取消,因为你正在默默地吃掉取消异常。

ThrowIfCancellationRequested does throw the OperationCanceledException. This causes the calling function to throw which is what gets you out of the task. The task class handles this exception (and others) and wraps them up into an AggregateException but that is for the caller, not the task. If you had modified your catch to use OperationCanceledException instead you would see it being called. But as I already said your task wouldn't cancel because you're silently eating the cancellation exception.

如果我想使用Task(而不是async),这就是我编写逻辑的方式/ await)。

Here's how I would have written the logic if I wanted to use Task (instead of async/await).

private void RunningTwoTasks ()
{
    ct = cts.Token;
    var t1 = Task.Factory.StartNew(UpdateText, "ONE");

    t1 = t1.ContinueWith(ant => UpdateText("TWO"), ct).ContinueWith(ant => UpdateText("THREE"), ct);
    t1 = t1.ContinueWith(t => richTextBox1.Invoke(new Action(() => richTextBox1.Text += "\n" + " ====== CANCELED ====== ")), TaskContinuationOptions.OnlyOnCanceled);
}

private void UpdateText ( object state )
{            
    for (int i = 0; i < 500; i++)
    {
        ct.ThrowIfCancellationRequested();
        richTextBox1.Invoke(new Action(() => richTextBox1.Text += "\n" + state + " " + i));
    }
}


任务正常工作,在有意义时检查取消。如果任务被取消,呼叫者将执行额外的工作。

The task just does its work, checking for cancellation when it makes sense. The caller does additional work if the task was cancelled.


这篇关于试图理解try / catch(AggregateException)不会取消我的任务。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆