Reputation: 45
1) This probably was asked a lot before, and I have read quite a lot about Sleep
vs WaitForSingleObject
, but still a little bit confused. As an example I have a simple background thread which is called from data-processing thread to show some message to the user without blocking data-processing thread. Which, in terms of performance (CPU usage / CPU time) is better in this case: http://pastebin.com/VuhfZUEg or http://pastebin.com/eciK92ze
I suspect that the shorter Sleep
time is and the more flags I have, the worse performance is. On other hand with longer Sleep
time performance will be better but reaction delay will increase, and with a lot of threads reaction delay will eventually become noticeable for user on low-end machine. Is that correct? So what is the best way to keep the "dormant", inactive threads?
2) Is SetEvent
blocking (SendMessage
) or non-blocking (PostMessage
)?
3) In TForm.OnCreate
event I have a following code:
procedure TFormSubsystem.FormCreate(Sender: TObject);
begin
Application.OnException:=LogApplicationException;
Application.OnActivate:=InitiateApplication;
end;
procedure TFormSubsystem.LogApplicationException(Sender: TObject; E: Exception);
var
ErrorFile: TextFile;
ErrorInfo: String;
begin
AssignFile(ErrorFile, AppPath+'Error.log');
if FileExists(AppPath+'Error.log') then
Append(ErrorFile)
else
Rewrite(ErrorFile);
ErrorInfo:=DateTimeToStr(Now)+' Unhandled exception';
if Assigned(Sender) then
ErrorInfo:=ErrorInfo+' in '+Sender.UnitName+'->'+Sender.ClassName;
ErrorInfo:=ErrorInfo+': '+E.Message;
try
WriteLn(ErrorFile, ErrorInfo);
finally
CloseFile(ErrorFile)
end;
end;
It's not the best way to log errors, but it's simple. The question is: What happens if there was an exception inside TSomeThreadAncestor.Execute
or inside a method called via Synchronize
?
4) What exactly is difference between Synchronize
and Queue
? Which one I should use when my background threads interact with GUI? I don't have race conditions and already use something like semaphores.
5) Is it safe to use such constructions?
procedure TShowBigDialoxBoxThread.Execute;
begin
while ThreadNotTerminated do begin
EventHandler.WaitFor(INFINITE);
if not(ThreadNotTerminated) then
Continue;
EventHandler.ResetEvent;
Synchronize(procedure begin
MessageDlgBig(FMsg, FDlgType, FButtons, FHelpContext, FDefaultButton, FDlgMinWidth);
end); // this kind of Synchronize call looks fishy
end;
end;
Or should I stick with calling a class method like in examples I provided above?
Edit: I currently use Delphi XE5.
Upvotes: 4
Views: 228
Reputation: 1349
Polling in a thread core is a bad practice if you could wait with a blocking function. What you need to learn is that a context change is very expensive in terms of CPU usage. The only case you should poll, when there is no other oprtion (you can't be notified when to do the work).
The difference is the following:
Polling:
Your thread gives the control to the thread controller by calling 'Sleep()' which forces a context change. After the given period (and a bit), the thread controller will give the control back to your thread initiating another context change. Your thread checks if it has anything to do and if not, it calls 'Sleep()' which forces another context change. So your thread will surely not respond while the 'Sleep()' period is over and forces at least 2 other context changes per 'Sleep()' period.
Blocking:
Your thread gives the control to the thread controller by calling 'Sleep()' which forces a context change, but will not wake up until you signal it. It means only one context change per operation, and instant answer from the signalled thread.
Also: 'SetEvent()' is not blocking, but you should have asked it in a different question.
Upvotes: 2