(Delphi fmx) Можете ли вы создавать элементы управления пользовательским интерфейсом в фоновом потоке, не блокируя пользовательский интерфейс - PullRequest
0 голосов
/ 25 октября 2019

Мне интересно, возможно ли создать элементы пользовательского интерфейса, даже полную форму, в фоновом потоке («конечно, без его использования»), и как только это будет сделано, сделайте его доступным для отображения в главном потоке.

Теперь относительно легко отделить трудоемкие операции с данными в фоновых потоках и синхронизировать результаты с основным потоком, но что, если создание самого пользовательского интерфейса является трудоемкой операцией?

Если возможно, у вас может быть быстрый экран запуска, а затем запуск фонового потока для создания набора форм. Всякий раз, когда кто-то готов, он включает пункт меню в главном потоке, чтобы его можно было использовать.

Я пробовал простой код, но он сразу же зависает. Возможно ли это?

Выполнить в основной программе:

    ...
    // declare var in main form 
    public
     { Public declarations }
     lForm : TForm ;

    ...
    // Execute e.g. with button click in main form 
    TThread.CreateAnonymousThread( procedure begin
    // this stops application from running when the form is show
    // in the synchronize part
    lForm := TForm1.Create(Self);

    TThread.Synchronize(nil,
     procedure begin
       // This does not stops the application but freezes the gui of course
       //lForm := TForm1.Create(Self);
       lForm.Parent := Self ;
       lForm.Show ;
      end );

   end ).Start ;`


    procedure TForm1.FormCreate(Sender: TObject);
    begin
     sleep(2000);
    end;
    ...

Если это невозможно, как вы могли бы сделать это в главном потоке, все еще «симулируя», что ваш основной поток отзывчив? (регулярно вызывая что-то вроде application.processmessages или около того?)

Я использую Delphi Rio 10.3, fmx framework.

Ответы [ 3 ]

2 голосов
/ 25 октября 2019

Мне интересно, возможно ли создать элементы пользовательского интерфейса, даже полную форму, в фоновом потоке («конечно, не используя его»), и, как только это будет сделано, сделать его доступным в основном потоке, чтобы

NO.

Создание и доступ к элементам управления пользовательского интерфейса из фонового потока не является потокобезопасным.

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

0 голосов
/ 27 октября 2019

Итак, в итоге, элементы управления пользовательским интерфейсом могут безопасно использоваться только в потоке, в котором они созданы, и вы не можете изменить это поведение после времени их создания (и сделать их «принадлежащими» другому потоку, как если бы они были созданытам, в первую очередь).

Может быть, хотя концептуально, создание форм, которые не взаимодействуют с другим, может работать, глядя на Как создать форму в DLL, встроенной в мое приложение? Я предполагаю, что и здесь форма действительно создается в другом потоке, возможно, даже в другом процессе, верно?

0 голосов
/ 25 октября 2019

Я обнаружил, что следующее не останавливается мгновенно, но если это чистая удача или мудрость, я не уверен ... Вместо этого, если сделать форму видимой в части синхронизации фонового потока, я делаю это «действительно» в основном потоке ...

(я мог бы понять, что, пока вы не предоставляете родителям элементы управления пользовательского интерфейса, они «безопасны». Как основной поток узнает об их существовании?)

Я мог бы проверить это немного позже.

procedure TTabbedForm.Button1Click(Sender: TObject);
begin


 TThread.CreateAnonymousThread( procedure begin
    lForm := TForm1.Create(Self);

    TThread.Synchronize(nil,
     procedure begin
       //lForm.Parent := Self ;
       //lForm.Show ;
       Button2.Enabled := True ;
      end );

   end ).Start ;

end;

procedure TTabbedForm.Button2Click(Sender: TObject);
begin
 if Assigned(lForm) then begin
  lForm.Parent := Self ;
  lForm.Show ;
 end;

end;

...