gpt4 book ai didi

multithreading - Delphi-帮助从另一个线程调用线程dll函数

转载 作者:行者123 更新时间:2023-12-04 05:30:35 25 4
gpt4 key购买 nike

我正在使用Delphi 2006,并且正在开发的应用程序存在一些问题。

我有一个创建线程的窗体,该线程调用一个执行冗长操作的函数,将其称为LengthyProcess。在LengthyProcess函数内部,我们还调用了几个Dll函数,这些函数也创建了自己的线程。

我遇到的问题是,如果不使用线程的Synchronize函数来调用LengthyProcess,则该线程将停止响应(主线程仍然可以正常响应)。我不想使用Synchronize,因为这意味着主线程正在等待LengthyProcess完成,因此无法实现创建单独线程的目的。

我已将问题跟踪到dll内部的一个创建线程然后调用WaitFor的函数,所有这些都使用TThread来完成。 WaitFor检查以查看CurrentThreadID是否等于MainThreadID,如果它等于MainThreadID,则它将调用CheckSychronization,一切都很好。因此,如果我们使用Synchronize,则CurrentThreadID将等于MainThreadID,但是,如果我们不使用Synchronize,则当然是CurrentThreadID <> MainThreadID,并且当发生这种情况时,WaitFor会告诉当前线程(我创建的线程)等待由线程创建的线程。 DLL,因此从未调用CheckSynchronization,并且我的线程最终永远等待dll中创建的线程。

我希望这是有道理的,抱歉,我不知道有什么更好的方法来解释它。还有其他人遇到过这个问题,请问该如何解决?

最佳答案

如果您的辅助线程“停止响应”,那么我认为它具有消息泵。 (否则,您需要解释它停止响应的内容。)您似乎还希望该线程能够检测到第三线程何时完成运行。 (这里的“主要”线程是VCL线程,根本不涉及。)

您尝试使用WaitFor,但是当发现它阻止时感到失望。但是,这就是它一贯的设计意图。它在主线程中的行为很奇怪,因此可以安全地从VCL线程进行调用,即使它最初并没有真正打算那样使用。

要处理消息并等待线程完成运行,您需要使用Windows API中的一个或多个wait functions。以 MsgWaitForMultipleObjects 开头。它可以等待各种类型的内核句柄(包括线程句柄),也可以在消息可用时通知您。这个想法是,您将在一个循环中调用该函数。如果显示消息可用,请对其进行处理,然后再次循环以继续等待。

以下仅是概述。您将需要查看所有使用的API函数的文档,并将其与您拥有的有关自己线程的其余知识结合起来。

procedure TSecondaryThread.Execute;
var
ret: DWord;
ThreadHandle: THandle;
Msg: TMsg;
begin
ThreadHandle := TertiaryThread.Handle;
repeat
ret := MsgWaitForMultipleObjects(1, ThreadHandle, False, Infinite, qs_AllEvents);
case ret of
Wait_Object_0: begin
// The thread terminated. Do something about it.
CloseHandle(ThreadHandle);
PostQuitMessage(0);
// Put *something* in the parameter so further calls to MWFMO
// will have a valid handle. May as well use a handle to something
// that will never become signaled so all we'll get are more
// messages. I'm pretty sure you can't pass an empty array of
// handles; there must be at least one, and it must be valid.
ThreadHandle := Self.Handle;
end;
Wait_Object_0 + 1: begin
// At least one message is available. Handle *all* of
// them before calling MsgWaitForMultipleObjects again
while PeekMessage(Msg, 0, 0, 0, pm_Remove) do
case Msg.Message of
wm_Quit: begin
// Do something about terminating the tertiary thread.
// Then stop the message loop and the waiting loop.
Exit;
end;
else begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
end;
Wait_Timeout: Assert(False, 'Infinity has passed');
Wait_Failed: RaiseLastOSError;
else Assert(False, 'Unexpected return value');
end;
until False;
end;

有关处理所有消息的部分很重要。调用 GetMessagePeekMessageWaitMessage时,操作系统会将队列中的所有消息都标记为“旧”,但是 MsgWaitForMultipleObjects仅在队列中存在"new"消息时才返回-在最后一次调用时到达 PeekMessage

关于multithreading - Delphi-帮助从另一个线程调用线程dll函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2114890/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com