多线程问题

时间:2015-05-21 13:01:12

标签: multithreading delphi

1)之前可能会有很多问题,我已经阅读了很多关于Sleep vs WaitForSingleObject的内容,但仍然有点困惑。作为一个例子,我有一个简单的后台线程,它从数据处理线程调用,向用户显示一些消息而不阻塞数据处理线程。在这种情况下,在性能(CPU使用率/ CPU时间)方面更好:http://pastebin.com/VuhfZUEghttp://pastebin.com/eciK92ze 我怀疑Sleep时间越短,标记越多,性能越差。另一方面,Sleep时间越长,性能越好但反应延迟会增加,并且在很多线程中反应延迟最终会对低端机器上的用户造成影响。那是对的吗?那么保持"休眠",非活动线程的最佳方法是什么?

2)SetEvent阻止(SendMessage)还是非阻塞(PostMessage)?

3)在TForm.OnCreate事件中,我有以下代码:

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;

这不是记录错误的最佳方式,但它很简单。问题是:如果TSomeThreadAncestor.Execute内或通过Synchronize调用的方法中存在异常,会发生什么?

4)SynchronizeQueue之间究竟有什么区别?当我的后台线程与GUI交互时我应该使用哪一个?我没有竞争条件,已经使用过信号量等信息。

5)使用这种结构是否安全?

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;

或者我应该坚持使用上面提供的示例中的类方法?

编辑: 我目前使用的是Delphi XE5。

1 个答案:

答案 0 :(得分:2)

如果您可以等待阻止功能,则在线程核心中进行轮询是一种不好的做法。您需要了解的是,上下文更改在CPU使用方面非常昂贵。当没有其他操作时,您应该轮询的唯一情况(您无法在何时开始工作时收到通知)。

不同之处如下:

民意调查:

您的线程通过调用“Sleep()”强制上下文更改来将控制权交给线程控制器。在给定的时间段(和一点点)之后,线程控制器会将控制权交还给您的线程,从而启动另一个上下文更改。你的线程检查它是否有任何操作,如果没有,它会调用'Sleep()'来强制另一个上下文更改。因此,当'Sleep()'时段结束时,您的线程肯定不会响应,并且每'Sleep()'时段强制至少 2 上下文更改

封闭:

您的线程通过调用“Sleep()”强制上下文更改将控件提供给线程控制器,但在您发出信号之前不会唤醒。这意味着每个操作只有一个上下文更改,并且从发出信号的线程中即时回答。

另外:'SetEvent()'没有阻止,但你应该在另一个问题中提出它。