主线程:
(是的,我现在停止主线程,我现在真的需要它进行测试,这是测试单元。我将在最后阶段在另一个线程中完成所有这些工作。)
代码:
function TFreHolder.GetVersion: TFreHolderVersion;
Var
Data : TBArray;
StrLen : Integer;
begin
SetLength(Data, 0);
FFrePro.SendCommand(PROTO_COMVERSION, Data);
ResetEvent(FAsyncMutex);
if (WaitForSingleObject(FAsyncMutex, PROTO_COMMANDTIMEOUT) = WAIT_TIMEOUT) Then
Begin
ShowMessage('Timeout');
ResetEvent(FAsyncMutex);
Exit;
End;
Result.DType := BytesToWord(FActivePackage.User.Parameters, 0);
Result.DVersion := BytesToWord(FActivePackage.User.Parameters, 2);
StrLen := BytesToByte(FActivePackage.User.Parameters, 4);
if StrLen < 32
then Result.DDesc := BytesToString(FActivePackage.User.Parameters, 5)
else Result.DDesc := BytesToString(FActivePackage.User.Parameters, 4);
在COM端口观察线程中:
procedure TFreHolder.CommandSwitcher(Package: TFreProPackage);
...
Begin
FActivePackage := Package;
SetEvent(FAsyncMutex)
End;
...
我总是看到超时消息,但如果我评论Waitforsingleobject,我可以看到字节和包即将到来。
我在构造函数中以这种方式创建了Event:
FAsyncMutex := CreateEvent(Nil, True, False, 'FRE_EVENT');
我的错误是什么?在获取结果之前,我需要等待CommandSwitcher函数的调用。
感谢。
答案 0 :(得分:6)
代码
ResetEvent(FAsyncMutex);
if (WaitForSingleObject(FAsyncMutex,...
绝对是一个错误,因为它忽略了线程的异步性质。
答案 1 :(得分:4)
假设另一个线程正在接收响应,然后在收到响应时发出FAsyncMutex
信号,那么您需要在调用ResetEvent()
之前调用SendCommand()
,而不是之后。如果线程恰好在发送方能够调用ResetEvent()
之前收到响应,那么它会通过清除它正在等待的条件来强制WaitForSingleObject()
超时。
此外,如果WaitForSingleObject()
超时等待事件发出信号,请不要致电ResetEvent()
,因为事件未被点击。
试试这个:
var
Ret: DWORD;
...
ResetEvent(FAsyncMutex);
FFrePro.SendCommand(PROTO_COMVERSION, Data);
Ret := WaitForSingleObject(FAsyncMutex, PROTO_COMMANDTIMEOUT);
if Ret <> WAIT_OBJECT_0 then
begin
if Ret = WAIT_TIMEOUT then
ShowMessage('Timeout')
else
ShowMessage('Error');
Exit;
end;