Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2013.03.22;
Скачать: [xml.tar.bz2];

Вниз

Поток и 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.55 MB
Время: 0.068 c
15-1345901427
Дмитрий С
2012-08-25 17:30
2013.03.22
Как получить уровень воспроизводимого звука?


15-1332016205
Юрий
2012-03-18 00:30
2013.03.22
С днем рождения ! 18 марта 2012 воскресенье


15-1334223202
brother
2012-04-12 13:33
2013.03.22
в win7 теперь это возможно?


15-1346322658
Артём
2012-08-30 14:30
2013.03.22
Как программно нажать на кнопку на сайте?


2-1339584024
IGray
2012-06-13 14:40
2013.03.22
ShowModal внутри try...except





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский