【发布时间】:2011-12-19 15:16:01
【问题描述】:
几年前,当某个应用必须非常快速地响应某些串行事件时,我将我的一个应用程序的串行处理转移到一个线程中。
它是在 BDS2006 中,有一个旧版本(一些 3.x?)它是通过在 tthread.execute 中包含这样的代码来完成的:
while ...
begin
events:=[evRxChar];
{ Prepare a stop event for killing a waiting communication wait. }
try
comport1.WaitForEvent(events,stopevent.handle,500);
if evRxChar in events then
ComPort1RxChar(comport1,comport1.InputCount); // method of thread.
on e: exception do {only logs} ;
end;
初始化就像
procedure TSerThread.initcomport(comportname:string='COM1');
begin
comport1:=tcomport.create(nil);
ComPort1.BaudRate:=br115200;
ComPort1.DataBits:=dbEight;
ComPort1.Port:=comportname;
ComPort1.StopBits:=sbOneStopBit;
ComPort1.Events:=[];
ComPort1.Connected:=true;
StopEvent := TEvent.Create(nil,{ManualReset}false,{InitialState}false,'StopEvent');
end;
rxchar 方法读取使用 comport1.readstr()
我最近不得不对此进行挖掘,并注意到它在我的具有 tcomport4 的 Delphi XE 中不起作用。在查看源代码时,我看到了以下评论 comport4 改变了它处理其内部线程的方式(“重叠”属性),但默认似乎是“真”有注释“经典”,我
假设这意味着与旧版本兼容。
注意协议是二进制的,所有的string,char ansistring,ansichar 的改变都和我在普通主线程版本中一样
现在是真正的问题:
- 有人让 tcomport4 在线程中工作吗?
- 上面有明显的错误吗?
- 还是我需要迁移到其他组件?
我仍在调试发生了什么,但我很着急,我在发布此消息时希望快速获得指针。
更新
我重新安装了一个旧的 turbo delphi 副本,并验证它在 v3 中可以正常工作。我在代码路径中修复了一个小错误,它与我的想法有点不同(不是在上面的代码中)
这让我可以更好地描述 dxe/comportv4 和 bds2006/comportv3 之间的行为; v4 代码生成更多的读取事件(数百次/秒)。似乎读取不会从传入队列中删除读取的字符。
更新 2
我对最新版本进行了快速测试,并进行了必要的重新排列(杀死字符串函数用于本质上的二进制协议)。我被卡住了一段时间,因为应用程序在启动时崩溃了,但那是因为我使用了 gnugettext,而 Comport 打包了一个不同的(甚至非 unicode?)版本。但在那之后它起作用了。
不幸的是,这些更改传播回生产版本(完全编写的协议解码)有点冒险,所以我必须测试中间版本(4.0 和 4.11f 之间)。我会在适当的时候这样做,有什么建议是最后一个 readstr(ansistring) 版本吗?
更新 3
最后,我只是重命名了 4.11f 单元并将它们与旧版本并行使用,将 4.11f 用于线程代码库并使用旧版本来维护现有代码。
从长远来看,我可能会简单地采用 waitforevent 代码并制作自己的版本。它的主要问题是无法查看等待是否在超时、停止事件或其他情况下终止。这意味着您需要另一个计时器,例如定期发送。
【问题讨论】:
-
TComPort 的确切版本是什么? (在各种 4.x 版本中存在很多差异和许多不同的奇怪错误。)
-
4.0 带有字符串“W.Postma 为 Delphi 2009 修复。2008 年 10 月”。 Afaik 我在 2009 年夏天在一个名为“tcomport4beta”的档案中得到它
-
那个版本有一些严重的错误。您使用的事件处理代码在 delphi 2009 中几乎无法使用,而在 XE 中则根本无法使用该版本。我会升级到稳定的发布版本。请注意,4.0 和 4.11 的字符串类型有所不同。从您发布的代码来看,您似乎没有为您的序列代码选择我使用 AnsiString 的默认路线,所以我建议您迁移到最新的 4.11 版本。
-
您对 Delphi 2009 年之前和 2009 年之后的 Unicode 问题了解多少? :-) 如您所知,在 Delphi 2006/2007 时代,一个 Char 很容易等于来自 com 端口的一个字节。到目前为止,delphi 中的 Char 是一个 Unicode 实体,虽然 TComPort 还不足以读取两个字节并将其称为“unicode 字符”,但如果您不移植到 Unicode Delphi,您仍然可能会遇到一些奇怪的事情正确。
-
缓冲区是 ansistring,comport devicename 仍然是“string”没关系。明天我会调试和玩更多,我这里唯一带有 comport 的桌面拒绝为远程调试器打开一个端口,可能是被旧的防病毒安装搞砸了。我不喜欢较新的 tcomports 的方向,基本上将 ascii 数据转换为 unicodestring。我自己将 XE 的相关定义添加到 .inc 中。不过不管怎样,这个专业没关系,我明天用更新的代码测试一下。