Counting connections and commands in a simulator (Delphi 7/Windows XP)
I was working in a simulator for testing connections and commands sending to a server. The simulator has some counters like Total of sent commands, successfully sent commands, fail sent commands, connection attempts, successf开发者_如何转开发ul connections, etc...
The code that I used is the following:
procedure TALClient.SendCommand;
begin
Try
dlgMain.IncrementIntConx; //Increments conn attemps
FTCP.Connect(1000);
If FTCP.Connected Then
Begin
dlgMain.IncrementConections; //increments successfully connections
try
dlgMain.IncrementIntSendCommand; //Increments command sent attemps (A)
FTCP.SendCmd(FCmd.FNemo + ' ' + FCmd.FParams); // (Z)
dlgMain.IncrementSendComm; //Increments sent Commands (B)
try
FParent.CS.Acquire;
FParent.FStatistic[Tag, FCmd.FTag].LastCodeResult := FTCP.LastCmdResult.NumericCode;
FParent.FStatistic[Tag, FCmd.FTag].LastMsgResult := FTCP.LastCmdResult.Text.Text;
FParent.CS.Release;
if ((FTCP.LastCmdResult.NumericCode) = (497)) then
Synchronize(UpdateCorrectCounters) //increments successfully responds from server
else
Synchronize(UpdateErrorCounters); //increments failed responds from server
except
Synchronize(UpdateErrorCounters);
end;
except
dlgMain.IncrementFailCommand; //increments failed commands (C)
end;
End
Else
Synchronize(UpdateErrorCounters); //Increment failed responses from sever
Finally
If FTCP.Connected Then
FTCP.Disconnect;
End
end;
I have changed the code to many many other ways, but it never works fine. The big problem is that the total count of sent commands is not equal to successfully sent commands plus failed sent commands. (in the code: A is not equal to B plus C). There are responses that I have never "seen" in the line marked as (Z), maybe "lost" responses...
So, what I am doing wrong?
I guess you are using multiple threads for your simulator. This looks like the classic Lost Updates problem to me. You have to synchronize the counter-incrementing code.
Incrementing a variable is NOT thread-safe:
Temp := CounterValue;
// If another thread intercepts here, we've got a lost update
Temp := Temp + 1;
CounterValue := Temp;
See this MSDN article to read more about concurrency issues.
If you only use counting you can use the Windows functions InterlockedIncrement
and InterlockedDecrement
and you won't need any locking.
精彩评论