我需要我的程序在每次TimeOutException读“泰晤士报”时捕捉到SerialPort,但是它没有做到这一点。实际上,程序在读取并抛出此异常时会中断,“I/O操作由于线程退出或应用程序请求而被中止”。
下面是SerialPort实例化的方式:
dxComm = class(System.Windows.Forms.Form)
private
protected
public
constructor;
serialPort1:System.IO.Ports.SerialPort;
thr:Thread;
method mythread;
end;
constructor DXComm;
begin
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
SerialPort1 := new System.Io.Ports.SerialPort();
thr:=nil;
end;
下面是如何创建线程:
thr:= new Thread(@mythread);
thr.Start;
以下是SerialPort设置:
case TypeDXCard.SelectedIndex of
0:
begin
DXProtocol := TDXProtocol.tDxTwo;
msglen := 6;
rmsglen := 5;
end;
1:
begin
DXProtocol := TDXProtocol.tDxExpress;
msglen:=0;
rmsglen:=0;
end;
else
begin
DXProtocol := TDXProtocol.tDxTwo;
msglen := 6;
rmsglen := 5;
end;
end;
dx := ord(DXProtocol);
if (SerialPort1 <> nil) then
begin
case CommPort.SelectedIndex of
0: SerialPort1.PortName := 'COM1';
1: SerialPort1.PortName := 'COM2';
2: SerialPort1.portName := 'COM3';
3: SerialPort1.PortName := 'COM4';
end;
case BaudRate.SelectedIndex of
0: SerialPort1.BaudRate := 1200;
1: SerialPort1.BaudRate := 2400;
2: SerialPort1.BaudRate := 4800;
3: SerialPort1.BaudRate := 9600;
4: SerialPort1.BaudRate := 19200;
5: SerialPort1.BaudRate := 38400;
6: SerialPort1.BaudRate := 57600;
7: SerialPort1.BaudRate := 115200;
end;
if (EvenParity.Checked) then
SerialPort1.Parity := System.IO.Ports.Parity.Even
else
SerialPort1.Parity := System.IO.Ports.Parity.None;
end;
with SerialPort1 do
begin
SerialPort1.DataBits:=8;
SerialPort1.DtrEnable:=true;
SerialPort1.ReadBufferSize:= 4096;
SerialPort1.ReadTimeout:=TimeOutDelay*2;
SerialPort1.RtsEnable:=true;
SerialPort1.StopBits:=System.IO.Ports.StopBits.One;
SerialPort1.WriteTimeout:=1000;
SerialPort1.Handshake := HandShake.None;
SerialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(@MySerialData);
end;
下面是处理SerialPort.Write的线程:
method DXcomm.mythread;
var x,y:Integer;
begin
while true do
begin
Thread.Sleep(ScanTime);
SerialPort1.RtsEnable:=true;
SerialPort1.DiscardOutBuffer;
SendMessage; <---------Assembles the bytes and sends it out
while SerialPort1.BytesToWrite>0 do;
thread.Sleep(4);
SerialPort1.DiscardInBuffer;
SerialPort1.RtsEnable:=false;
if (stopthread) then
break;
end;
end;
下面是从序列化端口读取字节的事件:
method DXComm.MySerialData(sender: System.Object; e:SerialDataReceivedEventArgs);
begin
if not SerialPort1.IsOpen then Exit;
try
SerialPort1.Read(RXMsg,0,5); <------Here is Where my program throws that exception when I check on TimeOutException down below.
if changeFlag then
begin
changeList.IncRxCnt;
FixUpChangeList;
end
else
ActiveUnit.Retreive;
except on ex: TimeOutException do <----This line of code fails.
//except on ex: Exception do <----This line of code works fine, but executes all the time instead of just only when there is an exception.
begin
//TimeOut Exception
ActiveUnit.Timeout;
SerialPort1.DiscardInBuffer;
SerialPort1.DiscardOutBuffer;
end;
end;
end;
我做错了什么?我需要抓住SerialPort.Read TimeOuts并采取适当的行动。
发布于 2011-08-31 14:31:14
我认为问题在于,我在自己的线程或用户定义的线程中写入序列化端口,并在另一个线程中读取序列化端口。我认为,事件数据接收是程序主线程的一部分。
正如Sebastian所指出的,从同一个线程中写和读应该解决我的串行通信问题。事实上,它似乎必须解决我的串行通信,虽然它略低于100%。这是一个时间问题,因为我的程序依赖于固定的时间延迟。
步骤:在我的线程中,我写到串口,等待某个时间从序列化端口读取响应。这似乎极大地改善了通信,但是现在我不等待数据接收事件在它看到输入缓冲区中的东西时触发。
如果我的想法或推理是错误的,请纠正我。
发布于 2011-08-24 05:56:12
似乎您正在使用串行端口作为表单上的组件,但在后台线程中执行读写操作?
或者,正如我所得到的,您在后台线程中写入,然后在其他随机线程上读取(调用对事件的响应的线程)。
这是一个问题,因为后台线程(内部)希望更新Serial 'Control',这是后台线程不允许的。问题还可能是等待读取的线程被在无限循环中写入的另一个线程中断,从而导致I/O异常。只是有点猜测而已。
第一次尝试:您必须动态创建串行端口(即不将它放在窗体上,而是通过代码实例化和配置它),或者(尽管极力阻止),将System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls
设置为false。
第二张照片:另一方面,我强烈建议确保只有一个线程与串口一起工作。不是在一条线上写,另一条线上读。在一个线程中执行与这个串行I/O相关的所有事情。读或写,但不要尝试同时从不同的线程。
发布于 2011-08-24 04:41:05
代替: SerialPort1.Read(RXMsg,0,5);
Delphi是否有一个串行函数,返回接收到的字符数和等待读取的字符数?
例如(在可能糟糕的伪代码中):
while (Not Timeout)
{
if (serialport1.characterswaiting)
{
SerialPort1.Read(RXMsg,0,5);
}
}
https://stackoverflow.com/questions/7165965
复制相似问题