Альтернатива TControl.Выполнять
Код 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, внутри другого потока, в том же приложении, без ожидания возврата?
EDIT
Такой подход мог бы смягчить проблему?
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. Окна созданные таким образом невосприимчивы к воссозданию и являются безопасными мишенями дляPostMessage
. Процедура окна для этого окна может затем переслать сообщение в вашу форму. И это безопасно, потому что процедура окна выполняется в потоке, связанном с его окном. В данном случае это поток GUI.В стороне, если вы вызываете
TControl.Perform
вне потока GUI, то это также неправильно. Ожидайте прерывистых и труднодиагностируемых сбоев.