Не удается освободить компонент вызывающего абонента - PullRequest
0 голосов
/ 31 мая 2019

Я пытаюсь освободить компонент, когда нажимаю на него. Итак, я написал самый простой код, который я мог себе представить, чтобы достичь этого: процедура, которая освобождает отправителя. Но на Delphi 7 (пробовал на Delphi XE 10, и он работал без ошибок), он иногда выдает случайное нарушение доступа или абстрактную ошибку. Самый простой способ повторить это - вставить 30 кнопок и назначить процедуру onclick с кодом ниже, а затем щелкнуть их.

Я попробовал два приведенных ниже кода, оба при нажатии:

procedure FreeMe(Sender: TObject);
begin
    TButton(Sender).Free;
end;

или

procedure FreeMe(Sender: TObject);
begin
    (Sender as TButton).Free;
end;

1 Ответ

1 голос
/ 31 мая 2019

Вам нужно отложить освобождение до полного завершения обработчика события кнопки OnClick. Важно, чтобы освобождение происходило, когда освобождаемый объект находится в режиме ожидания, а не в процессе обработки чего-либо.

Один из способов сделать это - использовать PostMessage(), например:

var
  MyReleaseWnd: HWND;

procedure TMyMainForm.FormCreate(Sender: TObject);
begin
  MyReleaseWnd := AllocateHWnd(MyReleaseWndProc);
end;

procedure TMyMainForm.FormDestroy(Sender: TObject);
begin
   DeallocateHWnd(MyReleaseWnd);
end;

procedure TMyMainForm.MyReleaseWndProc(var Message: TMessage);
begin
  if Message.Msg = CM_RELEASE then
    TObject(Msg.LParam).Free
  else
    Message.Result := DefWindowProc(MyReleaseWnd, Message.Msg, Message.WParam, Message.LParam);
end;

procedure DelayFreeMe(Sender: TObject);
begin
  PostMessage(MyReleaseWnd, CM_RELEASE, 0, LPARAM(Sender));
end;

В качестве альтернативы, в 10.2 Токио и позже вы можете использовать TThread.ForceQueue() вместо:

procedure DelayFreeMe(Sender: TObject);
begin
  TThread.ForceQueue(nil, Sender.Free);
end;

В любом случае, вы можете сделать это:

procedure TSomeForm.ButtonClick(Sender: TObject);
begin
  DelayFreeMe(Sender);
end;
...