Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2013.03.22;
Скачать: CL | DM;

Вниз

Поток и ShowModal (Delphi2009)   Найти похожие ветки 

 
NatashaZ ©   (2012-05-31 20:29) [0]

Здравствуйте!
Почему при вызове из неосновного потока форма вызывается по Showmodal, но не закрывается потом по нажатию на [X] или кнопку Exit (Button1), на клике которой процедура Close. Если вызывать ту же форму из основного потока программы, то форма закрывается нормально и так и так. Я слышала, что из потоков лучше не работать с визуальными объектами и может из-за этого проблема, но может есть какой-то обход данной проблемы?


 
sniknik ©   (2012-05-31 20:33) [1]

не "лучше не работать", а нельзя, не "с визуальными объектами" а полностью с VCL.

> обход данной проблемы?
переписать VCL. или, невероятно конечно, понимаю, но - подумать и изменить логику программы.


 
NatashaZ ©   (2012-05-31 20:37) [2]

А если попробовать вызвать процедуру, описанную в TForm, а уже из неё вызвать ShowModal? Как думаете, получится?
Просто очень нужно, что бы во время работы потока при возникновении  определенной ситуации выдавалось сообщение с определенным текстом. Вот не могу понять пока как бы сделать, что бы работало именно модальное окно. Поиском искала, но ответа про showmodal и потоки не нашла :(


 
Давайте будем жрать!   (2012-05-31 20:59) [3]

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


 
NatashaZ ©   (2012-05-31 21:01) [4]


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

А пример такого кода можете привести? Заранее благодарна.


 
NatashaZ ©   (2012-05-31 21:03) [5]

Я так понимаю, что это при помощи SendMessage(Form1,...) делается, но как именно?


 
NatashaZ ©   (2012-05-31 21:04) [6]

Самое главное - поток в это время не должен производить никакие операции, пока не закроется модальное окно.


 
Давайте будем жрать!   (2012-05-31 21:09) [7]

const
 MyMessage = WM_USER + 42;

type
 TMyMainForm = class(TForm)
   procedure WmMyMessage(var AMessage: TMessage); message MyMessage;
 end;

procedure TMyMainForm.WmMyMessage;
begin
 if модальная_форма_ещё_не_показана then
   with TMyModalForm.Create(Application) do
     try
       ShowModal;
     finally
       Free;
     end;
end;

procedure TMyThread.Execute;
begin
 for I := 1 to 1000000 do begin
   безумно_сложные_вычисления(I);
   if I mod 1000 = 0 then
     SendMessage(MainFormHandle, MyMessage, 0, 0);
 end;
end;

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


 
NatashaZ ©   (2012-05-31 21:09) [8]

Вроде еще нашла вариант с вызовом Synchronize(). Может так можно будет что-то сделать?


 
Давайте будем жрать!   (2012-05-31 21:11) [9]

Ну, в принципе, "поток в это время не должен производить никакие операции" сильно меняет задачу. И да, в таком случае Synchronize() уместен, но лучше воспользоваться советом [1].


 
NatashaZ ©   (2012-05-31 21:16) [10]

Спасибо за код. Домашнее задание решила так: MainFormHandle должно быть Application.MyMainForm.handle


 
Давайте будем жрать!   (2012-05-31 21:20) [11]

только вот ни к Application, ни к формам из потока обращаться нельзя, так что надо придумать, как форма потоку свой хэндл отдаст


 
NatashaZ ©   (2012-05-31 21:25) [12]


> но лучше воспользоваться советом [1].

Пока никак не  придумала, что можно поменять в логике задачи. Вычисляется результат по одной формуле и если результат равен 0, то выдаем диалог (вызываем форму с возможностью ввода числового значения в Edit). Дальше это значение записывается в переменную Z (Z объявлена глобальной переменной) по закрытию формы и дальше используется в том же потоке. Потоку нужно просто получить от пользователя следующее значение при результате 0. Поэтому модальное окно и нужно вызвать прямо из потока, приостановив все действия до закрытия формы с присвоением значения переменной Z.
Если есть мысли, как можно изменить логику, то очень буду признательна.


 
Давайте будем жрать!   (2012-05-31 21:33) [13]

во-первых, глобальная переменная -- это само по себе плохо.
во-вторых, надо делать что-то вроде

procedure TMyThread.Syncronized;
begin
 with TMyModalForm.Create(Application) do
   try
     ShowModal;
     Z := Edit1.Text; // Z -- поле TMyThread, а не глобальная переменная
   finally
     Free;
   end;
end;

procedure TMyThread.Execute;
begin
 if Formula() = 0 then
  Synchronize(Synchronized);
 ...
end;


 
NatashaZ ©   (2012-05-31 21:35) [14]


> только вот ни к Application, ни к формам из потока обращаться
> нельзя, так что надо придумать, как форма потоку свой хэндл
> отдаст

Ну почему же?
Такая конструкция разве допускается в потоке SendMessage(Form1.Handle,...)?
Ну или может поток создать так: MyThread.Create(Form1)?


 
NatashaZ ©   (2012-05-31 21:37) [15]


> во-первых, глобальная переменная -- это само по себе плохо.

Спасибо за код. Эта переменная используется потом не только в этом потоке и не только в этом юните. Поэтому решила её объявить глобально, доступной для всех юнитов.


 
Давайте будем жрать!   (2012-05-31 21:45) [16]


> Такая конструкция разве допускается в потоке SendMessage(Form1.
> Handle,...)
Не допускается.


> Ну или может поток создать так: MyThread.Create(Form1)?
Возможно. Думай дальше.


> переменная используется потом не только в этом потоке и
> не только в этом юните. Поэтому решила её объявить глобально,
>  доступной для всех юнитов.
http://www.gunsmoker.ru/2011/04/blog-post.html


 
Сергей М. ©   (2012-05-31 21:50) [17]


> NatashaZ


> нужно, что бы во время работы потока при возникновении  
> определенной ситуации выдавалось сообщение с определенным
> текстом


MessageBox


 
Max   (2012-05-31 21:52) [18]


> Просто очень нужно, что бы во время работы потока при возникновении
>  определенной ситуации выдавалось сообщение с определенным
> текстом

Windows.MessageBox


 
Max   (2012-05-31 21:53) [19]


> Сергей М

опередил :)


 
Давайте будем жрать!   (2012-05-31 21:55) [20]

Ввести числовое значение надо, толку тут с месаджбокса?


 
NatashaZ ©   (2012-05-31 21:57) [21]

На счет хэндла подумаю еще, поэкспериментирую.
Спасибо за ссылку по поводу переменных. Но уменя такая ситуация, что после отработки потока должны поменяться аж 5 штук переменных, объявленных ранее и используемых потом в других потоках и юнитах программы. Как в таком случае использовать  изолированные переменные в потоке или той же формы ввода, если потом переменные еще гда-то понадобятся, причем сразу 3 штуки в одной функции, которая в свою очередь должна будет вернуть 2 переменных? То же вычисление корней квадратного уравнения - как далее использовать полученные корни в других функциях без записи их значений в объявленные заранее глобальные переменные?


 
NatashaZ ©   (2012-05-31 21:58) [22]


> Windows.MessageBox

Не подходит, потому что

> Ввести числовое значение надо


 
Max   (2012-05-31 22:00) [23]


> Ввести числовое значение надо, толку тут с месаджбокса?

куда ввести? в первом сообщении не было ни о каком вводе


 
Давайте будем жрать!   (2012-05-31 22:03) [24]


> На счет хэндла подумаю еще, поэкспериментирую.
Подумать нелишне, но SendMessage в данном случае неактуален.


> а должны поменяться аж 5 штук переменных, объявленных ранее
> и используемых потом в других потоках и юнитах программы
Нужно создать объект, который будет инкапсулировать эти данные и записывать в который будет только модальная форма (ну, или код, выполняемый после закрытия формы), а читать все остальные. Плюс почитать, что такое singleton.


 
NatashaZ ©   (2012-05-31 22:05) [25]

Может я не так выразилась, но под глобальной переменной я имела в виду переменные объявленные так:
type
 TForm1 = class(TForm)
...
 protected
...
 private
 { Private declarations }
 public
 { Public declarations }
// variables
pA, pB, pC, iX, iZ,:integer;
...
end;

var...

implementation...


 
NatashaZ ©   (2012-05-31 22:07) [26]


> куда ввести? в первом сообщении не было ни о каком вводе

Я написала подробности в сообщении №12. Просто не знала, что они так важны в моем вопросе.


 
Leonid Troyanovsky ©   (2012-05-31 22:47) [27]


> NatashaZ ©   (31.05.12 22:07) [26]

Synchronize forever!

--
Regards, LVT.


 
NatashaZ ©   (2012-05-31 22:55) [28]


> Synchronize forever!

Спасибо, я тоже что-то уже склоняюсь к этому варианту.

Всем спасибо за помощь!


 
Dennis I. Komarov ©   (2012-06-01 00:52) [29]


> > Такая конструкция разве допускается в потоке SendMessage(Form1.
> > Handle,...)
> Не допускается.
>

Почему?


 
Давайте будем жрать!   (2012-06-01 10:33) [30]

Вызов vcl"ной функции TЧтоТоТам.GetHandle из потока — атата. Мог бы и сам догадаться.


 
ProgRAMmer Dimonych ©   (2012-06-01 10:53) [31]

> [30] Давайте будем жрать!   (01.06.12 10:33)

Некрасиво, конечно, но когда форма уже создана и в ближайшее время удаляться не будет, а доступ только для чтения - почему нет? Вешать синхронизацию на всё подряд - это не жизнь.


 
Anatoly Podgoretsky ©   (2012-06-01 11:18) [32]

> ProgRAMmer Dimonych  (01.06.2012 10:53:31)  [31]

А не вешать смерть


 
Давайте будем жрать!   (2012-06-01 11:21) [33]


> когда форма уже создана и в ближайшее время удаляться не
> будет
...то в самом примитивном варианте она передаёт свой хэндл потоку, который хэндл копирует и использует по своему усмотрению.


> почему нет
Потому что хэндл — не поле, а свойство, то бишь замаскированный вызов функции. Последствия непредсказуемы.


 
Dennis I. Komarov ©   (2012-06-03 11:52) [34]


> Давайте будем жрать!   (01.06.12 10:33) [30]

упс, я сюда посмотрел:SendMessage(MainFormHandle, MyMessage, 0, 0);, пардона примите... :-[


 
ProgRAMmer Dimonych ©   (2012-06-04 12:58) [35]

> [32] Anatoly Podgoretsky ©   (01.06.12 11:18)

> [33] Давайте будем жрать!   (01.06.12 11:21)

В теории-то понятно. И что реализация может поменяться со всеми последствиями - тоже ясно. И что нехорошо - очевидно.

Но поскольку на протяжении жизни формы меняться оно не будет, после её создания GetHandle() выполняет присваивание с проверкой условия, которое всегда будет истинным, - без синхронизации этого конкретного обращения всё работает отлично. Т.е. делать неправильно, но можно, если понимать, на каком расстоянии от ноги летит пуля. Зато количество навесного кода сокращается - и намного легче рассмотреть синхронизацию там, где это действительно критично: операции записи, создание/удаление экземпляров.


 
Leonid Troyanovsky ©   (2012-06-05 00:20) [36]


> ProgRAMmer Dimonych ©   (04.06.12 12:58) [35]

> Но поскольку на протяжении жизни формы меняться оно не будет

Оно ж не факт. Готов к оному?

--
Regards, LVT.


 
Германн ©   (2012-06-05 01:35) [37]


> Но поскольку на протяжении жизни формы меняться оно не будет

Ещё как будет! Сделай поиск в исходниках VCL вызовов функции RecreateWnd.


 
ProgRAMmer Dimonych ©   (2012-06-05 11:13) [38]

> [37] Германн ©   (05.06.12 01:35)
>
> > Но поскольку на протяжении жизни формы меняться оно не
> будет
>
> Ещё как будет! Сделай поиск в исходниках VCL вызовов функции
> RecreateWnd.

Кроме Dock() ничего опасного не нашёл: когда форма уже отображена, менять BorderStyle и т.п. минимум странно.

Хотя, повторяюсь, прекрасно понимаю, что отстаиваю право на жизнь для грязного трюка, который работает только при многих "если". И классика жанра с одним GUI-потоком для меня всегда была в приоритете.



Страницы: 1 вся ветка

Текущий архив: 2013.03.22;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.049 c
15-1348000202
Юрий
2012-09-19 00:30
2013.03.22
С днем рождения ! 19 сентября 2012 среда


2-1348424060
buddypetrovich
2012-09-23 22:14
2013.03.22
serversocket1 vs clientsocket1


2-1333633351
Jimmy
2012-04-05 17:42
2013.03.22
Как правильно отобразить картинку с полупрозрачными пикселями?


15-1337806793
TStas
2012-05-24 00:59
2013.03.22
Чайнотский вопрос про батники


3-1277448717
pavel_guzhanov
2010-06-25 10:51
2013.03.22
Можно ли сравнить два набора данных?