Sonic Son'edit
Sonic Son'edit

Reputation: 45

Multithreading questions

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

Answers (1)

mg30rg
mg30rg

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

Related Questions