发生了'System.OperationCanceledException'类型的异常

use*_*122 4 c# exception cancellation parallel.foreach

我正在实现一个Parallel.ForEach循环来完成一些工作,但是由于未处理的异常而导致了问题,而我认为我处理了取消.

为了尝试解决这个问题,我在winform中进行了一个简单的测试设置.它有一个开始按钮,一个取消按钮和一个输出标签.

代码:

public partial class Form1 : Form
{
    CancellationTokenSource cts = new CancellationTokenSource();

    public Form1()
    {
        InitializeComponent();
    }

    private async void button1_Click(object sender, EventArgs e)
    {
        output.Text = "Running";

        try
        {
            var runTask = Task<string>.Factory.StartNew(() => Run());
            await runTask;
            this.output.Text = runTask.Result;
        }
        catch(Exception ex)
        {
            throw ex;
        }
    }

    private string Run()
    {
        int useThreads = Environment.ProcessorCount - 2 < 1 ? 1 : Environment.ProcessorCount - 2;

        ParallelOptions options = new ParallelOptions() { MaxDegreeOfParallelism = useThreads, CancellationToken = cts.Token };

        options.CancellationToken.Register(() => ActionOnCancel());

        List<int> somelist =new List<int>();

        for(int i = 0; i < 100; i++)
            somelist.Add(i);

        Parallel.ForEach(somelist, options, (row, loopstate) =>
        {
            if(loopstate.ShouldExitCurrentIteration || loopstate.IsExceptional)
                loopstate.Stop();

            Thread.Sleep(1000);

        });

        return "Done";
    }

    private void ActionOnCancel()
    {
        output.Text= "Cancelled";
    }

    private void button2_Click(object sender, EventArgs e)
    {
        cts.Cancel();
    }
Run Code Online (Sandbox Code Playgroud)

当我运行程序并点击取消按钮(触发button2_Click)时,我继续收到此错误:

mscorlib.dll中出现"System.OperationCanceledException"类型的异常,但未在用户代码中处理

附加信息:操作已取消.

如果存在此异常的处理程序,则可以安全地继续该程序.

调试器突出显示Parallel.ForEach部分.但为什么???我以为我通过CancellationToken处理了取消更正.

ex中的异常消息并没有给我任何清晰的说明:"{"操作被取消了."}"呃......是啊....这是意图......

我在俯瞰什么?问候,

Matthijs

Cal*_*ith 8

始终抛出此异常.如果在CancellationTokenSource上调用cancel方法,则在访问Parallel Tasks时必须处理OperationCanceledException.

try
{
    Parallel.ForEach(somelist, options, (row, loopstate) =>
    {
        if(loopstate.ShouldExitCurrentIteration || loopstate.IsExceptional)
            loopstate.Stop();

        Thread.Sleep(1000);

    });
}
catch (OperationCanceledException)
{
    // Handle the cancelled Task
}
Run Code Online (Sandbox Code Playgroud)


Mir*_*Mir 1

CancellationToken.Register() 提供了一种向取消添加回调的方法,但不会根据 OperationCanceledException 来“处理”它。

我建议您也在 Run() 方法中放置一个 try/catch 块。