Форум: "Начинающим";
Текущий архив: 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.063 c