Reputation: 387
Main thread:
(Yes, I do stop main thread right now, I really need it right now for tests, this is test unit. I will do all this stuff in another thread during final stage.)
Code:
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);
In the COM-port watching thread:
procedure TFreHolder.CommandSwitcher(Package: TFreProPackage);
...
Begin
FActivePackage := Package;
SetEvent(FAsyncMutex)
End;
...
I always see timeout message, but if I comment Waitforsingleobject I can see that bytes and packages are coming.
I have created Event in Constructor this way:
FAsyncMutex := CreateEvent(Nil, True, False, 'FRE_EVENT');
What is my mistake? I need to wait the call of CommandSwitcher function before grabbing the results.
Thanks.
Upvotes: 0
Views: 2404
Reputation: 598029
Assuming that another thread is receiving the response and then signaling FAsyncMutex
when it has been received, then you need to call ResetEvent()
before calling SendCommand()
, not after. If the thread happens to receive the response before the sender is able to call ResetEvent()
then it is forcing WaitForSingleObject()
to timeout by clearing the condition it is waiting for.
Also, if WaitForSingleObject()
times out waiting for an event to be signaled, do not call ResetEvent()
since the event is not singaled.
Try this:
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;
Upvotes: 4
Reputation: 27493
Well the code
ResetEvent(FAsyncMutex);
if (WaitForSingleObject(FAsyncMutex,...
is definitely a mistake because it ignores the async nature of threads.
Upvotes: 6