gpt4 book ai didi

c# - 系统.IO.IOException : A device attached to the system is not functioning C# . NET 4.0

转载 作者:IT王子 更新时间:2023-10-29 04:28:06 25 4
gpt4 key购买 nike

我构建了一个从串口读取和写入数据的 C# 应用程序。连接到串行端口的设备是一个 FTDI USB 到串行转换器,它通过 XBee 无线模块与硬件通信。硬件测试电池模块的容量和稳态电压等。这些测试需要几天才能完成。

时不时地,串行端口似乎停止响应并抛出 System.IO.IOException: A device attached to the system is not functioning 错误。

这是堆栈跟踪:

at system.IO.Ports.InternalResources.WinIOError
at system.IO.Ports.SerialStream.EndWrite
at system.IO.Ports.SerialStream.Write
at system.IO.Ports.SerialPort.Write
at BatteryCharger.CommunicationClass.ApiTransmission

在抛出此错误后,将抛出 System.UnauthorizedAccessException: Access to the port is denied 错误,并且每次软件尝试写入端口时都会出现此错误,并且在我停止之前它永远不会恢复调试并重新启动软件只是为了几天后发生同样的事情。

如何防止此错误发生,或者有没有办法在错误的 catch 语句中成功地从这些错误中恢复?

我在后台工作线程中连续读取串行端口并从不同的线程写入。

我也已经尝试过该论坛上建议的所有遗留错误处理点点滴滴,但它们似乎都没有任何区别。该错误发生在 windows XP Pro SP3 32 位和 Windows7 Pro 32 位上。

这是 CommunicationClass.cs - 串行传输代码。

    public static bool ApiTransmission(TXpacket transmission)
{
//clear all previous data that may have been in the buffer before doing a transmission
Variables.dataParserPacket_buff.Clear();
//TXpacket xbeetransmision = new TXpacket();
byte[] packet = transmission.GeneratePacket();

try
{
if (_serialPort.IsOpen)
{
#if Console
Log.write("TX-Packet: " + StringHandler.listToString(packet.ToList<byte>()));
#endif
_serialPort.Write(packet, 0, packet.Length);
Thread.Sleep(100);
}
else
{
#if Console
Log.write("serial port is closed");
#endif
return false;
}
}
catch (UnauthorizedAccessException ex)
{
MessageBox.Show(ex.ToString());
Log.write("UnauthorizedAccessException");
}
catch (IOException ex)
{
MessageBox.Show(ex.ToString());
Log.write("IOexception");
//_serialPort.Close();
//Thread.Sleep(100);
//_serialPort.Open();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
#if Console
Log.write(ex.ToString());
#endif
}
return true;

}

这就是我初始化串口的方式

    public CommunicationClass(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits)
{
_analysePacketBGW.DoWork += new DoWorkEventHandler(_analysePacketBGW_DoWork);
_analysePacketBGW.WorkerReportsProgress = true;
_analysePacketBGW.WorkerSupportsCancellation = true;

_readBGW.DoWork += new DoWorkEventHandler(_readThread_DoWork);
_readBGW.WorkerSupportsCancellation = true;
_readBGW.WorkerReportsProgress = true;

_parserStarterBGW.DoWork += new DoWorkEventHandler(_parserStarterThread_DoWork);
_parserStarterBGW.WorkerSupportsCancellation = true;
_parserStarterBGW.WorkerReportsProgress = true;
if (_readBGW != null)
{
_readBGW.CancelAsync();
}

_serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);

//SerialPortFixer.Execute(portName);
//Thread.Sleep(1000);
//using (_serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits))
//{
// //_serialPort.Open();
//}

_serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(_serialPort_ErrorReceived);

_dataqueuepp = new ManualResetEvent(false);

_serialPort.Open();
_readBGW.RunWorkerAsync();
_parserStarterBGW.RunWorkerAsync();
CommunicationClass.PacketReceived += new DataPacketReceived(CommunicationClass_PacketReceived);
}

以及处理串口读取的后台worker

    void _readThread_DoWork(object sender, DoWorkEventArgs e)
{
#if Console
Log.write("Read()");
#endif
while (!_readBGW.CancellationPending)
{
try
{
int message = _serialPort.ReadByte();
try
{
Variables.dataQueue.Enqueue(message);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + " " + message.ToString());
}
_dataqueuepp.Set();
//Console.Write(String.Format("{0:X2}", message) + " ");
}
catch (TimeoutException) { Log.write("read timeout"); }
catch (IOException) { Log.write("read IOException"); }
catch (ThreadAbortException) { Log.write("read thread aborted"); }
catch (Exception ex) { MessageBox.Show(ex.ToString()); }
finally { }
}
}

我现在将重写代码以从同一个线程读取和写入串口,看看是否有任何不同。

编辑

根据 Jim 的评论,我在 IOException Catch 语句中添加了以下内容:

        catch (IOException ex)
{
MessageBox.Show(ex.ToString());
Log.write("IOexception");
_readBGW.CancelAsync();
Thread.Sleep(100);
_serialPort.Close();
Thread.Sleep(100);
_serialPort.Open();
Thread.Sleep(100);
_readBGW.RunWorkerAsync();
_serialPort.Write(packet, 0, packet.Length);
}

希望通过停止后台 worker 的 _serialPort.Read、关闭端口、重新打开端口、再次运行后台 worker 并尝试再次编写相同的命令足以成功地从此错误中恢复。 MessageBox 仍会阻止代码,以便我可以看到错误发生的时间并可以监控它是如何恢复的。

我不喜欢像这样给软件打补丁,但如果它能用,那它也能用。

编辑 2

添加上面的代码后,我的软件再次崩溃,但现在当我调用 _serialPort.Close() 时它会抛出“UnauthorizedAccessException - 访问端口被拒绝”;

System.UnauthorizedAccessException was unhandled
Message=Access to the port is denied.
Source=System
StackTrace:
at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
at System.IO.Ports.InternalResources.WinIOError()
at System.IO.Ports.SerialStream.Dispose(Boolean disposing)
at System.IO.Stream.Close()
at System.IO.Ports.SerialPort.Dispose(Boolean disposing)
at System.IO.Ports.SerialPort.Close()
at BatteryCharger.CommunicationClass.ApiTransmission(TXpacket transmission) in E:\Mijn Documenten\Research\Copy of BatteryCharger_V12\BatteryCharger\CommunicationClass.cs:line 436
at BatteryCharger.CommunicationClass.tx1(TXpacket packet, String callingMethod) in E:\Mijn Documenten\Research\Copy of BatteryCharger_V12\BatteryCharger\CommunicationClass.cs:line 356
at BatteryCharger.XBee.setPin(String pinID, Byte status, XBee slave) in E:\Mijn Documenten\Research\Copy of BatteryCharger_V12\BatteryCharger\XBee.cs:line 215
at BatteryCharger.XBee.setPins(Int32 pins, XBee slave) in E:\Mijn Documenten\Research\Copy of BatteryCharger_V12\BatteryCharger\XBee.cs:line 177
at BatteryCharger.BatteryCharger.requestVoltage(Int32 block) in E:\Mijn Documenten\Research\Copy of BatteryCharger_V12\BatteryCharger\BatteryCharger.cs:line 595
at BatteryCharger.BatteryCharger.requestVoltages() in E:\Mijn Documenten\Research\Copy of BatteryCharger_V12\BatteryCharger\BatteryCharger.cs:line 612
at BatteryCharger.Form1.RunCommandOn(List`1 battList, Int32 command, Double lowerLimit, Double upperLimit) in E:\Mijn Documenten\Research\Copy of BatteryCharger_V12\BatteryCharger\Form1.cs:line 522
at BatteryCharger.Form1.chargeBlock(Int32 blockNr, Double lowerLimit, Double upperLimit) in E:\Mijn Documenten\Research\Copy of BatteryCharger_V12\BatteryCharger\Form1.cs:line 689
at BatteryCharger.Form1.<btnCheckCapacities_Click>b__13() in E:\Mijn Documenten\Research\Copy of BatteryCharger_V12\BatteryCharger\Form1.cs:line 619
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:

这是怎么回事?

最佳答案

根据我的经验,10 次中有 9 次这种情况发生在另一个线程(终止或未终止)没有对硬件端口的独占访问权时。

尝试使用 SyncLock 为端口操作编写一个包装器,最重要的是它的打开/关闭。 https://msdn.microsoft.com/en-us/library/3a86s51t.aspx

类似地,我通常认为 try/catches 控制硬件是一种不好的做法,除非有足够的异常处理。

原因(可能适用于此)是在抛出异常的情况下硬件将锁定,更糟糕的是,异常将掩盖错误的真正原因。

在上面的代码中,我看到了样式中的消息输出

DebugPrint(ex.Message); 

这样做会更好

DebugPrint(ex.tostring()); 

因为这也会导出异常中的堆栈跟踪。

我要做的是实现一个异常记录器,将这些异常写入正在运行的计算机中某处的(带时间戳的)文本文件。跟踪记录的异常数据(以及所有相关信息)可以更好地理解为什么会发生这种情况。

关于c# - 系统.IO.IOException : A device attached to the system is not functioning C# . NET 4.0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18729146/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com