Delphi - 如何防止在写入LPT端口时应用程序挂起

4

我有一个应用程序,可以直接将命令写入一些特定打印机的LPT1端口。代码如下:

AssignFile(t, 'LPT1');
Rewrite(t);

Write(t,#27 + '@');          // initialize
Sleep(50);                   // avoid buffer fill
Write(t,#27#32 + Chr(0));    // set default font
...

问题在于当打印机未连接到端口时,第一个Write指令不起作用,它只是挂起并且整个线程被锁定。

有没有一种方法可以为这些指令定义超时,或者您可以推荐另一个库来完成此工作?如果它具有类似Delphi中的Write函数,那就太好了,因为使用这种方法的代码量非常大,更改所有代码将非常困难。


我忘了提到"t"是这样定义的:var t: TextFile; - Valentin Istrate
1
是的,有一种方法可以为通信设备上的操作定义超时时间。请参阅 GetCommTimeoutsSetCommTimeouts 函数。 - Val Marinov
2个回答

5

您可以使用SetCommTimeouts为打印机句柄配置超时。要从TextFile变量获取句柄,请将其强制转换为TTextRec并读取Handle字段:

var
  CommTimeouts: TCommTimeouts;

CommTimeouts.WriteTotalTimeoutConstant := DesiredTimeout;
Win32Check(SetCommTimeouts(TTextRec(t).Handle, CommTimeouts));

在设置所需字段之前,您可能希望先调用GetCommTimeouts来发现其他字段的默认值。


2
将您的打印代码移至一个独立的线程中。内置的文本文件函数没有任何超时机制,但是您可以告诉操作系统,在您决定时间过长时取消任何挂起的I/O操作。
我建议从CancelSynchronousIo开始,它会取消给定线程上的所有I/O。这应该允许您保留所有现有的Write调用。准备好处理被取消时的失败情况。
该函数需要Windows Vista或更高版本,这在现今不应该成为问题,但如果您仍需要支持Windows XP,则需要使用CreateFile打开端口以进行重叠的I/O。然后您可以使用CancelIoCancelIoEx。由于内置的Delphi函数不支持重叠操作,因此您需要替换所有的Write调用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接