13

如果 Delphi 代码是用 synchronize 编写的,以序列化对 VCL 主线程的访问,但是这段代码在非 VCL 应用程序中使用,它会与应用程序的主线程同步还是完全没有效果?


例子:

procedure TMyThread.Execute;
begin

  // ... other code

  Synchronize(SomeMethod);

  // ...

end;

让我们假设

  • 它是一个非 VCL 应用程序,它有一个在无限循环中执行的主线程(或直到终止)
  • 主线程不CheckSynchronize直接调用或在 WakeMainThread 处理程序中调用
  • 辅助线程运行并执行 Synchronize(SomeMethod) 就像上面的示例一样

线程会挂在 Synchronize(SomeMethod) 行上吗?

4

3 回答 3

9

TThread为非 VCL 程序提供检查同步队列的工具,因此它们可以继续使用期望同步其方法的多线程库。这CheckSynchronize. 请记住,检查队列是应用程序的工作,而不是您的库的工作。

只要应用程序履行合同的一部分,您的使用Synchronize应该没问题。但是,如果没有,那么您的程序将无法正常工作,但我不知道会出现什么确切症状。悬挂当然听起来很合理。

于 2012-05-21T16:48:01.307 回答
6

在非 VCL 应用程序中使用同步是否危险?

是的,这很危险。如果您的主线程没有调用CheckSynchronize,那么Synchronize将导致死锁。

让我们假设

  • 它是一个非 VCL 应用程序,它有一个在无限循环中执行的主线程(或直到终止)
  • 主线程不CheckSynchronize直接调用或在WakeMainThread处理程序中调用
  • 辅助线程Synchronize(SomeMethod)像上面的示例一样运行和执行

线会不会挂Synchronize(SomeMethod)在线上?

调用Synchronize将阻塞后台线程,直到主线程调用CheckSynchronize. 因此,如果主线程从不调用CheckSynchronize,后台线程将无限期阻塞。

以下程序说明了这一点:

program TheBigSleep;

{$APPTYPE CONSOLE}

uses
  SysUtils, Classes, Windows;

type
  TMyThread = class(TThread)
  protected
    procedure Execute; override;
  end;

procedure TMyThread.Execute;
begin
  Synchronize(SysUtils.Beep);
end;

begin
  with TMyThread.Create do
    WaitForSingleObject(Handle, INFINITE);
    //don't call WaitFor since that, in turn, calls CheckSynchronize
end.
于 2012-05-21T17:51:41.157 回答
1

Since you are putting the Delphi code in a library for other apps to use, I would not advise using Synchronize() at all, since you thread has no concept of what is going on outside of itself. A better choice is to have the thread expose a callback event that the thread can call in its own context when needed, and then let the app provide a callback function handler that decides the best way to synchronize with the app's main thread as needed.

于 2012-05-22T17:39:02.743 回答