【问题标题】:Program throwing OperationCanceledException despite catching it程序抛出 OperationCanceledException 尽管捕获它
【发布时间】:2017-11-07 09:06:14
【问题描述】:

我正在尝试使用令牌来取消由 Task.Run 启动的任务。我从 microsoft 网站获取了模式:https://msdn.microsoft.com/pl-pl/library/hh160373(v=vs.110).aspx

这是我的代码:

public static class Sender
{

    public static async Task sendData(NetworkController nc) {
        await Task.Run(() => {
            IPEndPoint endPoint = new IPEndPoint(nc.serverIp, nc.dataPort);
            byte[] end = Encoding.ASCII.GetBytes("end");
            while (true) {
                if (Painting.pointsQueue.Count > 0 && !nc.paintingSenderToken.IsCancellationRequested) {

                    byte[] sendbuf = Encoding.ASCII.GetBytes(Painting.color.ToString());
                    nc.socket.SendTo(sendbuf, endPoint);

                    do {
                        sendbuf = Painting.pointsQueue.Take();
                        nc.socket.SendTo(sendbuf, endPoint);
                    } while (sendbuf != end && !nc.paintingSenderToken.IsCancellationRequested);

                }
                else if (nc.paintingSenderToken.IsCancellationRequested) {
                    nc.paintingSenderToken.ThrowIfCancellationRequested();
                    return;
                }
            }
        }, nc.paintingSenderToken);
    }
}

我在这里开始这个任务:

    public void stopController() {
        try {
            paintingSenderTokenSource.Cancel();
            senderTask.Wait();
        } catch(AggregateException e) {
            string message = "";
            foreach (var ie in e.InnerExceptions)
                message += ie.GetType().Name + ": " + ie.Message + "\n";
            MessageBox.Show(message, "Przerwano wysylanie");
        }
        finally {
            paintingSenderTokenSource.Dispose();
            byte[] message = Encoding.ASCII.GetBytes("disconnect");
            IPEndPoint endPoint = new IPEndPoint(serverIp, serverPort);
            socket.SendTo(message, endPoint);
            socket.Close();
            mw.setStatus("disconnected");
        }

    }

    public async void initialize() {
        Task t = Reciver.waitForRespond(this);
        sendMessage("connect");
        mw.setStatus("connecting");
        if (await Task.WhenAny(t, Task.Delay(5000)) == t) {
            mw.setStatus("connected");
            Painting.pointsQueue = new System.Collections.Concurrent.BlockingCollection<byte[]>();
            senderTask = Sender.sendData(this);
        }
        else {
            mw.setStatus("failed");
        }
    }
}

initialize() 方法中,我正在等待来自服务器的响应,如果得到响应,我将在sendData() 方法中启动新线程。它在静态类中使代码更干净。如果我想停止这个线程,我会调用stopController() 方法。在微软网站我们可以阅读:

当调用线程调用 Task.Wait 方法时,CancellationToken.ThrowIfCancellationRequested 方法会引发 OperationCanceledException 异常,该异常在 catch 块中进行处理。

但是我的程序在“sendData()”方法中的nc.paintingSenderToken.ThrowIfCancellationRequested(); 上中断,并且错误表明未处理 OperationCanceledException。我从微软网站启动程序,它运行良好。我想我所做的一切都像他们一样,但不幸的是它并没有像它应该的那样工作。

【问题讨论】:

  • 快速提问,您是否启用了“仅启用我的代码”?
  • 是的,我已启用它。

标签: c# wpf multithreading exception-handling


【解决方案1】:

您可能启用了“仅启用我的代码”。 要查找设置,请转到:

工具 => 选项 => 调试 => 常规 => 仅启用我的代码

如果选中此复选框,您是否可以取消选中它然后再次运行您的应用程序。

【讨论】:

  • 嗯,它有所帮助,但并不完全正确。程序现在没有中断,但它冻结在“senderTask.Wait()”上。在调试器中,我可以看到该线程仍在运行。
猜你喜欢
  • 1970-01-01
  • 2019-12-18
  • 2017-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-15
相关资源
最近更新 更多