Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 01.08.2009, 14:29   #1
Freezer
Пользователь
 
Аватар для Freezer
 
Регистрация: 04.02.2007
Сообщений: 37
По умолчанию TThread и GUI

Здравствуйте уважаемые коллеги!
У меня появилась следующая задачка. У меня в программе можно создавать любое количество потоков, которые выполняют каждый свой скрипт. Так в скрипте эсть возможность вызывать свои диалоговые формы, и воспламеняющиеся формы(как в QIP). Формы я реализовал свои, как наследники от TForm, но это не столь важно. Проблема заключается в том, что эти формы должны быть абсолютно независимыми, и фукция которая их создает, должна видеть все остальные формы что б правильно рассчитать координаты новой формы. Это нужно для воспламеняющиеся форм, они появляются одна над другой, возле трая. Так вот, с одним или двомя потоками всьо ок, но если из запустить 5-10 штук, начинают вылазить глюки синхронизации. То Access Vialation, то глюки прорисовки. Перелопатил кучу доки, но нигде нормально не описана работа потоков с интерфейсом, максимум вызов через synchronize().
У кого есть идеи, или ссылки на нужную инфу?
Помогите пожалуйста!
Не грузи, и не грузим будешь...
Freezer вне форума Ответить с цитированием
Старый 01.08.2009, 16:48   #2
Ntlegend
Форумчанин
 
Аватар для Ntlegend
 
Регистрация: 12.05.2007
Сообщений: 373
По умолчанию

попробуй завести глобальную переменную с которой читай координаты предыдущей формы.. и пиши новые координаты низа (для седующей формы).. когда окно появляется увеличивай переменную когда убирается уменьшай.. все просчто.. но тут может возникнуть проблема с доступом к ней.. так как пару потоков сразу на нее ломануться.. как и везде "одновременно" они не будут получать доступ.. какойто поток на долю микросекунды раньше.. а остальные пусть проверяють занятость переменной. и если знята - то ждать..
Перемен! - требуют наши сердца. Перемен! - требуют наши глаза.
В нашем смехе и в наших слезах, И в пульсации вен:
"Перемен!Мы ждем перемен!"
Ntlegend вне форума Ответить с цитированием
Старый 01.08.2009, 17:36   #3
Freezer
Пользователь
 
Аватар для Freezer
 
Регистрация: 04.02.2007
Сообщений: 37
По умолчанию

Хм.. Я делаю приблезительно так же, но проблема немного не в том. Я немного намутил в вопросе, попробую упростить:

Есть форма с кнопочкой, если нажать на нее должны создаться 10 потоков, и каждый из них должен создать еще по форме и показать из ShowModal.
И того у меня должно быть 10 модальных форм которые не блокируют друг друга.

Как сделать чтобы эта вся штука не вылетала???
Не грузи, и не грузим будешь...
Freezer вне форума Ответить с цитированием
Старый 01.08.2009, 19:33   #4
alexBlack
Участник клуба
 
Регистрация: 12.10.2007
Сообщений: 1,204
По умолчанию

Посмотрите пример
Вложения
Тип файла: rar test.rar (2.7 Кб, 20 просмотров)
alexBlack вне форума Ответить с цитированием
Старый 02.08.2009, 00:06   #5
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Идея такова.
1. создать в общем классе, или как общую переменную список TList.
2. в этот самый список, при создании каждого потока добовлять себя(этот поток) при вызове деструктора данного потока удалять из этого списка.
3. если речь о модальных окнах, то не понятно, причем тут общая переменная. При создании каждого потока, есть возможность передавать параметры (или же создать свой-во у потомка TThread), собственно сделать какую-то структуру с вашей информацией и создать в главном (родительском потоке) там где и список с потоками эту структуру. После при создании потока (дочернего) передавать ему указатель на эту структуру, так же не забывать отключить FreeOnTerminate у дочерних потоков.

В дополнее скажу, для синхронизации можно использовать события SetEvent (и другое см. в MSDN), или же просто критические секции CriticalSection (так же в MSDN) очень эффективно если требуется синхронизированное обращение к общим данным.
BOBAH13 вне форума Ответить с цитированием
Старый 02.08.2009, 11:21   #6
s.Creator
Форумчанин
 
Регистрация: 28.09.2008
Сообщений: 344
По умолчанию

Цитата:
Сообщение от Freezer Посмотреть сообщение
Хм.. Я делаю приблезительно так же, но проблема немного не в том. Я немного намутил в вопросе, попробую упростить:

Есть форма с кнопочкой, если нажать на нее должны создаться 10 потоков, и каждый из них должен создать еще по форме и показать из ShowModal.
И того у меня должно быть 10 модальных форм которые не блокируют друг друга.

Как сделать чтобы эта вся штука не вылетала???
А почему именно модальные? Что они блокируют?
Может лучше использовать
Код:
FormStyle = fsStayOnTop
а блокировать потоки другими методами?
s.Creator вне форума Ответить с цитированием
Старый 03.08.2009, 11:21   #7
Freezer
Пользователь
 
Аватар для Freezer
 
Регистрация: 04.02.2007
Сообщений: 37
По умолчанию

alexBlack - спасибо за пример. Честно говоря не подумал про такой вариант. Правда немного смущает выполнение всего в основном потоке с постоянно проверяющим таймером "а не нужно ли что-то создать или удалить", но если не удастся полностью переложить GUI на потоки, то буду развивать эту идею.

Цитата:
Идея такова.
1. создать в общем классе, или как общую переменную список TList.
2. в этот самый список, при создании каждого потока добовлять себя(этот поток) при вызове деструктора данного потока удалять из этого списка.
Ну это ясно, это стандартный прием. Не пойму как это относится к вопросу. Возможно я что-то не так понимаю, если так то объясните подробнее.

Цитата:
3. если речь о модальных окнах, то не понятно, причем тут общая переменная. При создании каждого потока, есть возможность передавать параметры (или же создать свой-во у потомка TThread), собственно сделать какую-то структуру с вашей информацией и создать в главном (родительском потоке) там где и список с потоками эту структуру. После при создании потока (дочернего) передавать ему указатель на эту структуру, так же не забывать отключить FreeOnTerminate у дочерних потоков.
Это конечно да, но я не знаю что может понадобится потоку. Как я описал выше, поток исполняет скрип юзера, а там может и с трая сказать "Выключи чайник", а может спросить диалогом "Вы действительно хотите удалить файл?". Поэтому как это впихнуть в структуру с информацией я что-то не пойму.



Цитата:
А почему именно модальные? Что они блокируют?
Блокируют дальнейшее выполнение кода и поток должен ожидать ModalResult. Конечно я пробовал и показывать обычные формы, а в коде писал
Код:
        repeat
          Application.ProcessMessages;
          if Application.Terminated then dlg.result := vcrCancel;
          Sleep(1);
        until dlg.result <> vcrNone;
но с каждым потоком, программа начинает все медленнее отвечать на запросы юзера. А поле 6-7 потоков, тормоза просто жуткие.
Не грузи, и не грузим будешь...
Freezer вне форума Ответить с цитированием
Старый 03.08.2009, 19:42   #8
s.Creator
Форумчанин
 
Регистрация: 28.09.2008
Сообщений: 344
По умолчанию

Может как-то так:
ThreadGUI.zip
s.Creator вне форума Ответить с цитированием
Старый 05.08.2009, 11:50   #9
Freezer
Пользователь
 
Аватар для Freezer
 
Регистрация: 04.02.2007
Сообщений: 37
По умолчанию

Спасибо всем кто ответил!
Интергировать формы коректно так и не получилось.
Сделал так, потоки создают переменную моего типа TMessageQuery куда записывают заголовок, текст, набор кнопок, тип диалога и т.д., помещают его в защищенный список TTreadList, и зацикливаются.
Код:
function KShowDialog(Caption : string; Text: String; Buttons : array of TVcButtonKind; Style : TVcMassageStyle; Icon : TVcIcon): TVcResult;
var q : TMessageQuery;
begin
  q := TMessageQuery.Create(Caption, Text, Buttons, Style, Icon);
  RList.Add(q);
  while (q.Result = vcrNone) and not (Application.Terminated) do begin
    Application.ProcessMessages;
    SleepEx(1, true);
  end;
  Result := q.Result;
  RList.Remove(q);
  q.Free;
end;
К стати метод TMessageQuery.GetResult тоже делал через TCriticalSection.

А в главном потоке по таймеру проверял не появилось ли чего нового в очереди, если появилось - создавал форму. Здесь же проверял не нажали чего на форме, если нажали
Код:
q.Result := dlg.result;
и прячу форму.

Правда это получилась эмуляция того что я хотел, но проблему решило! Еще раз всем спасибо, кто принял участие в обсуждении!
Не грузи, и не грузим будешь...
Freezer вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
TThread в С++ Builder alun C++ Builder 7 02.06.2010 21:55
Метод Synchronize класса TThread EdNovice Общие вопросы Delphi 10 01.08.2009 14:47
COM, TThread, обращение по таймеру Антон Ю.Б. Общие вопросы Delphi 2 17.02.2009 09:23
использование TThread amandra Общие вопросы Delphi 6 03.05.2008 03:13
Stack owerflow - глюки с TThread IOrist Общие вопросы Delphi 4 11.11.2007 09:13