我创建了一个异步处理串行端口的类。我用它与调制解调器通信。我不知道为什么,但有时,当我关闭我的应用程序时,我会出现蓝屏并且我的计算机会重新启动。我一步一步地记录了我的代码,但是当蓝屏出现并且我的计算机重新启动时,我记录数据的文件只包含空格。因此,我不知道 BSOD 的原因可能是什么。
我仔细查看了我的代码,发现了问题的几个可能原因(我正在寻找所有可能导致访问未分配内存并导致 AV 异常的原因)。
当我重新考虑异步操作的想法时,我想到了一些事情。请验证这些是否正确:
1) WaitCommEvent() 获取一个指向重叠结构的指针。因此,如果我在函数内部调用 WaitCommEvent() 然后离开函数,重叠的结构不能是局部变量,对吧?事件掩码变量和事件句柄也是,对吧?
2) ReadFile() 和 WriteFile() 也采用变量的引用或指针。因此,在重叠的读取或写入操作完成之前,所有这些变量都必须是可访问的,对吧?
3) 我只调用一次 WaitCommEvent() 并在一个循环中检查它的结果,同时做其他事情。因为我不知道如何终止异步操作(有可能吗?),所以当我销毁我的保留串口句柄的类时,我首先关闭句柄,然后在使用的重叠结构中等待事件调用 WaitCommEvent() 函数时。我这样做是为了确保异步等待通信事件的线程不会访问我的类中被破坏的任何字段。这是个好主意还是愚蠢?
try
CloseHandle(FSerialPortHandle);
if Assigned(FWaitCommEvent) then
FWaitCommEvent.WaitFor(INFINITE);
finally
FSerialPortHandle := INVALID_HANDLE_VALUE;
FreeAndNil(FWaitCommEvent);
end;
在我注意到所有这些之前,第一点和第二点中提到的大多数变量都是调用上述三个方法的函数的局部变量。这可能是 BSOD 的原因还是我应该在我的代码中寻找其他一些错误?
当我更正代码时,BSOD 停止发生,但这可能是巧合。你怎么想?
任何想法将不胜感激。提前致谢。
我阅读了 CancelIo() 函数文档,它指出此方法取消调用线程发出的所有 I/O 操作。如果我知道 WaitCommEvent() 是由与调用 CancelIo() 的线程不同的线程发出的,那么在调用 CancelIo() 后等待 FWaitCommEvent 是否可以?
if Assigned(FWaitCommEvent) and CancelIo(FSerialPortHandle) then
begin
FWaitCommEvent.WaitFor(INFINITE);
FreeAndNil(FWaitCommEvent);
end;
我检查了在这种情况下会发生什么,调用这段代码的线程没有死锁,即使它没有发出 WaitCommEvent()。我在 Windows 7 上进行了测试(如果重要的话)。我可以保留代码原样还是危险?也许我误解了文档,这就是我提出问题的原因。我很抱歉问了这么多问题,但我真的需要确定这一点。
谢谢。