![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Поток и ShowModal (Delphi2009)
NatashaZ © (2012-05-31 20:29:00)Здравствуйте!
Почему при вызове из неосновного потока форма вызывается по Showmodal, но не закрывается потом по нажатию на [X] или кнопку Exit (Button1), на клике которой процедура Close. Если вызывать ту же форму из основного потока программы, то форма закрывается нормально и так и так. Я слышала, что из потоков лучше не работать с визуальными объектами и может из-за этого проблема, но может есть какой-то обход данной проблемы?
Max (2012-05-31 21:52:00) [21]
> Просто очень нужно, что бы во время работы потока при возникновении
> определенной ситуации выдавалось сообщение с определенным
> текстом
Windows.MessageBox
Сергей М. (2012-05-31 21:50:00) [22]
> NatashaZ
> нужно, что бы во время работы потока при возникновении
> определенной ситуации выдавалось сообщение с определенным
> текстом
MessageBox
Давайте будем жрать! (2012-05-31 21:45:00) [23]
> Такая конструкция разве допускается в потоке SendMessage(Form1.
> Handle,...)
Не допускается.
> Ну или может поток создать так: MyThread.Create(Form1)?
Возможно. Думай дальше.
> переменная используется потом не только в этом потоке и
> не только в этом юните. Поэтому решила её объявить глобально,
> доступной для всех юнитов.
http://www.gunsmoker.ru/2011/04/blog-post.html
NatashaZ (2012-05-31 21:37:00) [24]
> во-первых, глобальная переменная -- это само по себе плохо.
Спасибо за код. Эта переменная используется потом не только в этом потоке и не только в этом юните. Поэтому решила её объявить глобально, доступной для всех юнитов.
NatashaZ (2012-05-31 21:35:00) [25]
> только вот ни к Application, ни к формам из потока обращаться
> нельзя, так что надо придумать, как форма потоку свой хэндл
> отдаст
Ну почему же?
Такая конструкция разве допускается в потоке SendMessage(Form1.Handle,...)?
Ну или может поток создать так: MyThread.Create(Form1)?
Давайте будем жрать! (2012-05-31 21:33:00) [26]во-первых, глобальная переменная -- это само по себе плохо.
во-вторых, надо делать что-то вроде
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:25:00) [27]
> но лучше воспользоваться советом [1].
Пока никак не придумала, что можно поменять в логике задачи. Вычисляется результат по одной формуле и если результат равен 0, то выдаем диалог (вызываем форму с возможностью ввода числового значения в Edit). Дальше это значение записывается в переменную Z (Z объявлена глобальной переменной) по закрытию формы и дальше используется в том же потоке. Потоку нужно просто получить от пользователя следующее значение при результате 0. Поэтому модальное окно и нужно вызвать прямо из потока, приостановив все действия до закрытия формы с присвоением значения переменной Z.
Если есть мысли, как можно изменить логику, то очень буду признательна.
Давайте будем жрать! (2012-05-31 21:20:00) [28]только вот ни к Application, ни к формам из потока обращаться нельзя, так что надо придумать, как форма потоку свой хэндл отдаст
NatashaZ (2012-05-31 21:16:00) [29]Спасибо за код. Домашнее задание решила так: MainFormHandle должно быть Application.MyMainForm.handle
Давайте будем жрать! (2012-05-31 21:11:00) [30]Ну, в принципе, "поток в это время не должен производить никакие операции" сильно меняет задачу. И да, в таком случае Synchronize() уместен, но лучше воспользоваться советом [1].
NatashaZ (2012-05-31 21:09:00) [31]Вроде еще нашла вариант с вызовом Synchronize(). Может так можно будет что-то сделать?
Давайте будем жрать! (2012-05-31 21:09:00) [32]
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:04:00) [33]Самое главное - поток в это время не должен производить никакие операции, пока не закроется модальное окно.
NatashaZ (2012-05-31 21:03:00) [34]Я так понимаю, что это при помощи SendMessage(Form1,...) делается, но как именно?
NatashaZ (2012-05-31 21:01:00) [35]
> из потока отправляешь пользовательское сообщение главной
> форме. главная форма отлавливает сообщение и выводит модальную
> форму.
А пример такого кода можете привести? Заранее благодарна.
Давайте будем жрать! (2012-05-31 20:59:00) [36]из потока отправляешь пользовательское сообщение главной форме. главная форма отлавливает сообщение и выводит модальную форму.
NatashaZ (2012-05-31 20:37:00) [37]А если попробовать вызвать процедуру, описанную в TForm, а уже из неё вызвать ShowModal? Как думаете, получится?
Просто очень нужно, что бы во время работы потока при возникновении определенной ситуации выдавалось сообщение с определенным текстом. Вот не могу понять пока как бы сделать, что бы работало именно модальное окно. Поиском искала, но ответа про showmodal и потоки не нашла :(
sniknik (2012-05-31 20:33:00) [38]не "лучше не работать", а нельзя, не "с визуальными объектами" а полностью с VCL.
> обход данной проблемы?
переписать VCL. или, невероятно конечно, понимаю, но - подумать и изменить логику программы.