SerialPort 中的错误关闭线程但不更改它的状态并且不引发异常

Error in SerialPort Closes Thread but don't change it's Status and don't raise an Exception

我正在使用下面的代码在单独的线程中阅读 SerialPort

我打开 Serial Port 并尝试 read a line。由于 Serial Port 中没有任何连接,因此出现错误。我期待一些 TimeoutException 被抛出,但是没有!没有抛出异常,任务停止工作!

据我所知,一个Task can be shutdown by returning from it, or throwing an exception,但这段代码也不行。任务停止工作,任务状态保持为 WaitingForActivation

这是怎么回事?我需要在我的应用程序中处理此类错误,但我看不到 SerialPort.

报告的任何类型的异常或错误

我还尝试进入 Tools/Options/Debugging 并关闭 "Enable Just My code (Managed only)",但这没有做任何事情。

代码是: (我将它放在单击按钮内,以便更容易复制。) (为了 运行 你需要一根 FTDI 电缆或类似的东西,并且没有任何东西连接到电缆上)。

private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (Thread.CurrentThread.Name != "Main")
        {
            Thread.CurrentThread.Name = "Main";
        }

        Debug.WriteLine(string.Format("Started from thread '{0}'.", Thread.CurrentThread.Name));
        TestTask = Task.Run(() =>
            {
                Thread.CurrentThread.Name = "TestTask";
                int i = 0;
                Debug.WriteLine(string.Format("Started from thread '{0}'.", Thread.CurrentThread.Name));
                while (true)
                {
                    try
                    {
                        SerialPort serialPort = new SerialPort("COM14"); 
                        while (!serialPort.IsOpen) serialPort.Open(); // Try to open the SerialPort.
                        Debug.WriteLine(string.Format("From Thread '{0}', Try to read now:", Thread.CurrentThread.Name));
                        string s = serialPort.ReadLine(); // here's the error.
                        i++; // this line is never executed.
                        Debug.WriteLine(string.Format("From Thread '{0}', Loop Count : {1}", Thread.CurrentThread.Name, i));
                    }                        
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);                            
                    }
                }
            }
            );
        while(true)
        {
            Debug.WriteLine(string.Format("From Thread '{0}', TestTask Status: {1}.", Thread.CurrentThread.Name, TestTask.Status));
            Thread.Sleep(500);
        }
        //try // I tried this before the 'while(true)' above to see if there were any Exceptions being thrown to the "outside" but no, nothing here.
        //{
        //    TestTask.Wait();
        //}
        //catch(AggregateException ae)
        //{
        //    ae.Flatten();
        //}
    }

程序的输出是这样的:

您遇到此问题的原因可能因与串行端口交互的模块而异。

但是,您需要检查一些事项才能从代码中获得您期望的结果。

首先,TestTask总是等待激活,只要while(true)存在无限循环。

其次,SerialPort.Readline不抛出TimeOutException等待接收到一行,unless you set the ReadTimeout propety to a non-zero value.

try-catch for exception in Task.Run 必须正常工作。 您可以在这个 极其简单的代码 示例中看到它的工作原理,如下所示:

var TestTask = Task.Run(() =>
{
    while (true)
    {
        try
        {
            throw new Exception();
        }                        
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);                            
        }
    }
});

最后,您仍然希望通过查看 Debug - Exception...(Ctrl+Alt+E) 检查您的 VS 调试器在遇到任何异常时的行为,其中它的选项列可能会有所不同,具体取决于 Just My Code 是否启用,以防您感到困惑。 (我个人更喜欢启用它)。

如果您想要捕获您的应用程序抛出的所有异常,无论它是否会在未来得到妥善处理,请检查该选项中的 Thrown 列 window. 这将导致 VS 调试器在每次抛出异常时中断。

线程被锁定在 ReadLine() 方法中,因为没有定义 ReadTimeout。线程确实仍在执行,没有错误或异常干扰它。

我只是没想到该方法会阻塞,因为代码文档没有指定该方法将无限期阻塞,直到收到换行符。但是 online documentation 说得很清楚:

By default, the ReadLine method will block until a line is received. If this behavior is undesirable, set the ReadTimeout property to any non-zero value to force the ReadLine method to throw a TimeoutException if a line is not available on the port.