Альтернатива TControl.Perform
TControl.Perform
код является:
var
Message: TMessage;
begin
Message.Msg := Msg;
Message.WParam := WParam;
Message.LParam := LParam;
Message.Result := 0;
if Self <> nil then WindowProc(Message);
Result := Message.Result;
Выполнение программы ожидает возврата, я прав?
Есть ли альтернатива для размещения сообщения в очереди TFORM, в другом потоке, в том же приложении, без ожидания возврата?
РЕДАКТИРОВАТЬ
Такой подход может смягчить проблему?
interface
const
WM_DOSTUFF = WM_APP + $001;
TMyForm = class(TForm)
{stuff}
public
{Other stuff}
procedure DoMyStuff(var Msg: TMessage); message WM_DOSTUFF;
{More stuff}
end;
var
MyHandle: HWND;
implementation
constructor TMyForm.Create(AOwner: TComponent);
begin
inherited;
MyHandle := AllocateHWnd(DoMyStuff);
end;
destructor TMyForm.Destroy;
begin
DeallocateHWnd(MyHandle);
inherited;
end;
И обычно используйте внутри потока:
PostMessage(MyHandle, WM_DOSTUFF, 0, 0);
1 ответ
Чтобы добавить сообщение в очередь потока, связанного с другим окном, необходимо использовать PostMessage
Функция Windows API.
PostMessage(WindowHandle, Msg, WParam, LParam);
Теперь, если вы делаете это в другом потоке из потока GUI, то вы не можете использовать Form.Handle
получить ручку окна. Это потому, что это приводит к гонке с потоком GUI. И если дескриптор необходимо воссоздать, он будет создан с привязкой к вашему потоку, а не к потоку GUI. Запомните правила: взаимодействуйте только с объектами VCL из потока GUI.
Так вы обычно не используете PostMessage
с дескриптором формы VCL, потому что вы не можете легко гарантировать, что сообщение будет доставлено в правильное окно. Даже если вы синхронизируете доступ к дескриптору окна, окно может быть воссоздано, и ваше сообщение не будет доставлено.
Самый простой способ доставить сообщения асинхронно - это вызвать TThread.Queue
, Это не требует дескриптора окна для работы и, таким образом, позволяет избежать всех проблем с привязкой объекта VCL к потоку GUI. Процедура, которую вы отправляете при звонке Queue
выполняется в потоке GUI и поэтому безопасно выполнять все операции VCL.
Если вы используете более раннюю версию Delphi, TThread.Queue
тогда это сложнее. Вы должны в этом случае использовать PostMessage
, Но вам придется направить сообщение в окно, не связанное с формой. Направьте его в окно, созданное с помощью AllocateHWnd
, Помните, что вы должны позвонить AllocateHWnd
в потоке GUI. Windows, созданные таким образом, защищены от повторного создания и являются безопасными объектами для PostMessage
, Оконная процедура для этого окна может затем переслать сообщение в вашу форму. И это безопасно, потому что оконная процедура выполняется в потоке, связанном с его окном. В этом случае это поток GUI.
Как в сторону, если вы звоните TControl.Perform
далеко от потока GUI, то это тоже неправильно. Ожидайте прерывистый и трудно диагностировать сбои.