我有一个问题,对于互联网上的任何人来说似乎都是一个很大的未知,当串行连接被板的内部异常中断时,我的 Windows 应用程序会卡住。
这是该问题的最简单示例:
最简单的C#代码,打开COM端口连接。
internal static class Program
{
private static SerialPortStream _serialPort;
static void Main()
{
_serialPort = new SerialPortStream("COM6", 9600, 8, Parity.None, StopBits.One);
_serialPort.Open();
}
}
Arduino 板代码,它将在短暂延迟后模拟内部异常。
void loop()
{
delay(500); //We wait 0.5 seconds to allow the COM port connection to "Successfully" be established, and so the .Open() call in C# won't throw an exception.
//We create an internal exception, in this instance we try to set an array size to a negative value
int index = -4;
byte* serialData = new byte[index];
}
这是重现此问题的非常简单的方法。
一些值得注意的信息:
感谢所有提供帮助的人!
您可以在 C# 程序中使用一些策略来处理这种情况:
读/写超时:
使用串行端口的读写超时是防止程序挂起的一种技术。如果 Arduino 在预定时间内没有做出反应,这允许您的应用程序捕获超时并处理问题。
_serialPort.ReadTimeout = 500;
_serialPort.WriteTimeout = 500;
异步通信:
避免阻塞主线程的一种方法是使用异步技术进行读写。您可以使用 Task, for Task.Run 来执行串行读数。
async Task ReadFromSerialPort()
{
try
{
while (true)
{
string data = await Task.Run(() => _serialPort.ReadLine());
}
}
catch (TimeoutException)
{
}
catch (Exception ex)
{
}
}
例外:
要处理异常,请将 Open 方法和所有随后的读取或写入包含在 try-catch 块中。通过这种方式,您可以记录错误,并可能在出现问题时尝试重新打开连接。
try
{
_serialPort.Open();
}
catch (UnauthorizedAccessException ex)
{
}
catch (IOException ex)
{
}
串口状态:
您可以密切关注串口的状况,如果它停止响应,可以将其关闭。为了确定端口是否仍然响应,必须执行不同的线程或作业。
取消标记:
如果您实现任何长时间运行的操作(例如从串行端口读取),请使用取消令牌。这使您能够在发生错误或活动时间比预期长时停止活动。 例如:
private static SerialPortStream _serialPort;
static async Task Main()
{
_serialPort = new SerialPortStream("COM6", 9600, 8, Parity.None, StopBits.One)
{
ReadTimeout = 500,
WriteTimeout = 500
};
try
{
_serialPort.Open();
await ReadFromSerialPort();
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
static async Task ReadFromSerialPort()
{
try
{
while (true)
{
string data = await Task.Run(() => _serialPort.ReadLine());
}
}
catch (TimeoutException)
{
}
catch (IOException ex)
{
}
catch (Exception ex)
{
}
}