为什么这个 Synchronize 过程不锁定主线程
Why doesn't this Synchronize procedure lock the main thread
我有以下代码:
TThread.Synchronize(nil,
procedure
begin
with Scope.New(TManualCaptchaForm.Create(img)) do
if It.ShowModal() = mrOk then
res := It.edtResolved.Text;
end
);
为什么多个TThreads
使用此程序同步时,表格会出现多次?我知道一个解决方法,没有什么不寻常的(例如没有其他 "hand-made" 与主线程同步的方法),但是 为什么我没有遇到锁定?
是的,Scope.New
有点智能指针,但是只有我看到TThread.Synchronize
并通过了关闭?文档说任何传递给 TThread.Synchronize
的 method/closure 都将在主线程中执行。显然,ShowModal
必须阻塞主线程,但它并没有这样做。对于我来说,任何其他 window 启动都充当主线程和泵同步队列是非常奇怪的。
P.秒。几乎 MVP:
TThread.Synchronize(nil,
procedure
var Form: TForm1;
begin
Form := TForm1.Create(nil);
try
Form.ShowModal();
finally
Form.Free;
end;
end
);
运行 此代码在 2+ 个线程中查看错误。无论如何,现在我知道同步队列由任何 window 消息循环泵送,而不仅仅是主窗体。
顺便说一句,我的问题是 "Why TThread.Synchronize
behave so unclear/not logically?",而不是我自己的代码。
这里的根本误解是,因为 .ShowModal
是一个阻塞调用,所以您 期望 它也会暂停消息处理。它不是。当您创建模态 window 时,模态 window 接管消息处理 - 它必须这样做,否则 window 将无法运行。主线程仍在处理消息循环,只是在不同的上下文中进行。
如果你想这样想,ShowModal
的行为很像 Application.ProcessMessages
。这与Synchronize
无关。如果您检查 ShowModal
的代码,您会发现:
{ ... }
Show;
try
SendMessage(Handle, CM_ACTIVATE, 0, 0);
ModalResult := 0;
{ *** Here is your message loop *** }
repeat
Application.HandleMessage;
if Application.Terminated then ModalResult := mrCancel else
if ModalResult <> 0 then CloseModal;
until ModalResult <> 0;
{ *** ------------------------- *** }
Result := ModalResult;
SendMessage(Handle, CM_DEACTIVATE, 0, 0);
if GetActiveWindow <> Handle then ActiveWindow := 0;
finally
Hide;
end;
{ ... }
如果你想在这里防止重新进入,你必须设计自己的显式方法。
我有以下代码:
TThread.Synchronize(nil,
procedure
begin
with Scope.New(TManualCaptchaForm.Create(img)) do
if It.ShowModal() = mrOk then
res := It.edtResolved.Text;
end
);
为什么多个TThreads
使用此程序同步时,表格会出现多次?我知道一个解决方法,没有什么不寻常的(例如没有其他 "hand-made" 与主线程同步的方法),但是 为什么我没有遇到锁定?
是的,Scope.New
有点智能指针,但是只有我看到TThread.Synchronize
并通过了关闭?文档说任何传递给 TThread.Synchronize
的 method/closure 都将在主线程中执行。显然,ShowModal
必须阻塞主线程,但它并没有这样做。对于我来说,任何其他 window 启动都充当主线程和泵同步队列是非常奇怪的。
P.秒。几乎 MVP:
TThread.Synchronize(nil,
procedure
var Form: TForm1;
begin
Form := TForm1.Create(nil);
try
Form.ShowModal();
finally
Form.Free;
end;
end
);
运行 此代码在 2+ 个线程中查看错误。无论如何,现在我知道同步队列由任何 window 消息循环泵送,而不仅仅是主窗体。
顺便说一句,我的问题是 "Why TThread.Synchronize
behave so unclear/not logically?",而不是我自己的代码。
这里的根本误解是,因为 .ShowModal
是一个阻塞调用,所以您 期望 它也会暂停消息处理。它不是。当您创建模态 window 时,模态 window 接管消息处理 - 它必须这样做,否则 window 将无法运行。主线程仍在处理消息循环,只是在不同的上下文中进行。
如果你想这样想,ShowModal
的行为很像 Application.ProcessMessages
。这与Synchronize
无关。如果您检查 ShowModal
的代码,您会发现:
{ ... }
Show;
try
SendMessage(Handle, CM_ACTIVATE, 0, 0);
ModalResult := 0;
{ *** Here is your message loop *** }
repeat
Application.HandleMessage;
if Application.Terminated then ModalResult := mrCancel else
if ModalResult <> 0 then CloseModal;
until ModalResult <> 0;
{ *** ------------------------- *** }
Result := ModalResult;
SendMessage(Handle, CM_DEACTIVATE, 0, 0);
if GetActiveWindow <> Handle then ActiveWindow := 0;
finally
Hide;
end;
{ ... }
如果你想在这里防止重新进入,你必须设计自己的显式方法。