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

时间:2015-06-25 12:04:38

标签: delphi

我有一个应用程序,它直接在LPT1端口上将命令写入某些专用打印机。代码如下所示:

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

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

问题在于,当打印机没有连接到端口时,第一个写入指令不会执行任何操作,它只是挂断并且整个线程都被锁定。

有没有办法为这些说明定义超时,或者你能推荐另一个可以完成这项工作的库吗?如果它有一个与Delphi类似的Write函数会很棒,因为使用这种方法的代码量非常大,而且很难改变所有代码。

2 个答案:

答案 0 :(得分:5)

您可以使用SetCommTimeouts配置打印机句柄的超时。要从TextFile变量中获取句柄,请将其输入TTextRec并阅读Handle字段:

var
  CommTimeouts: TCommTimeouts;

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

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

答案 1 :(得分:2)

将您的打印代码移至单独的主题。内置的文本文件函数没有任何超时机制,但是只要您认为已经过了太多时间,就可以告诉操作系统取消任何挂起的I / O操作。

我从CancelSynchronousIo开始,取消了给定线程上的所有I / O.它应该允许您保留所有现有的Write来电。准备好在被取消时失败。

该功能需要Windows Vista或更高版本,现在不应该成为问题,但如果您仍然需要Windows XP的支持,它将无法运行。在这种情况下,您需要使用CreateFile打开重叠I / O端口。然后,您可以使用CancelIoCancelIoEx。您需要替换所有Write次来电,因为内置的Delphi功能不支持重叠操作。