Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

"Нити" и showmessage [D6, D7, Win2k, WinXP]


Пономарев Андрей ©   (2006-03-13 14:18:00) 

Добрый день, господа!

Столкнулся с проблемой.
Пытаюсь разнести свою программу на две нити: VCL и некоторая бизнес-логика. Для связи между ними прописал интерфейс Listener, который реализуется формой. Соответственно, нитка бизнес-логики в нужные моменты вызывает те или иные методы Listener'a.

Проблема:
Попытка сделать showmessage в методе формы (реализующем операцию интерфейса) вызывает ошибку 'Canvas doesnt allow drawing'. От случая к случаю.

Одно из решений:
Сливаю класс бизнес-логики в Thread, его несущий, для каждого метода интерфейса предусматриваю делегата, и вызываю их через Synchronize(). Все работает.

Не нравится:
Слияние класса бизнес-логики и TThread (сейчас TThread просто владеет экземпляром этого класса, БЛ ничего не знает о "нитке"), в то время как отдельный Thread - это лишь одна из возможных реализаций. И вообще, хотелось бы иметь класс БЛ без упоминаний о VCL (все пишется на самом деле на C++Builder).

Есть ли другие способы синхронизации, которые позволили бы решить эту задачу, не засоряя класс БЛ подробностями управления "нитками"?

Спасибо.


Игорь Шевченко   (2006-03-13 17:44:00) [1]

Пономарев Андрей   (13.03.06 17:37) [12]


> С точки зрения работоспособности оба метода подходят.


Нет, первый метод не подходит, в чем ты сам убедился, написав пост № 0 :)

Если бы не было разделения по потокам (а нафига они, потоки, собственно, в паттерне observer ?), то подошли бы оба метода, а в случае с многопоточностью и VCL эти обстоятельства накладывают свои ограничения.


> оригинал всего этого писался на C++Builder, поэтому IListener
> там не означал автоматически подсчет ссылок


При реализации интерфейса в TForm, собственно тоже подсчета ссылок нету, судя по коду в TComponent._AddRef и TComponent._Release...


Пономарев Андрей   (2006-03-13 17:37:00) [2]

Рискую прослыть навязчивым, но все же отвечу. :)


> Но никто не мешает реализовать интерфейс в классе-посреднике,
>  не привязанном к VCL

Никто не мешает, я ни в коем случае с этим не спорю.
Посредник, "совмещающий" потоки, в любом случае, необходим - без него просто работать не будет. Однако принципа работы у него может быть, как минимум, два: либо пляски бубном вокруг Synchronize() и передача параметров через атрибуты, либо посылка windows-сообщений форме.

В первом случае мы имеем (грубо)
TForm1 = class(TForm, IListener)
 public:
   procedure SomeEvent(Sender : TBusinessController; a : TSomeClass; ...);
   procedure SomeOtherEvent(Sender : TBusinessController; a : TSomeClass; ...);
end;


Во втором случае -
TForm1 = class(TForm)
 public:
   procedure SomeEvent(var Message : ...); message ...;
   procedure SomeOtherEvent(var Message : ...); message ...;
end;


С точки зрения работоспособности оба метода подходят.
Мне больше нравится первый.
Второй же, вероятно, второй является общепринятым.

Я правильно понял?

(оригинал всего этого писался на C++Builder, поэтому IListener там не означал автоматически подсчет ссылок и тому подобные "прелести" - это был обычный абстрактный класс)


Игорь Шевченко   (2006-03-13 17:17:00) [3]

Пономарев Андрей   (13.03.06 16:34) [10]


> Жестко. :) Может быть и неверно. Однако примерно так я понимаю
> паттерн Observer. То, что нужны действия по синхронизации,
>  и непосредственный вызов методов формы не катит - это понятно.
>  Но реализация формой интерфейса Listener... не знаю...
> по-моему, это весьма стандартный подход.


Паттерн правильно понимается, а вот конкретная его реализация не верна.
Но никто не мешает реализовать интерфейс в классе-посреднике, не привязанном к VCL


Пономарев Андрей   (2006-03-13 16:34:00) [4]

Всем спасибо за внимание.


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

Ну да, пока так и делаю. Не очень нравится, конечно, но терпимо.


> > Соответственно, нитка бизнес-логики в нужные моменты
> вызывает
> > те или иные методы Listener'a.
>
> А это неверно.

Жестко. :) Может быть и неверно. Однако примерно так я понимаю паттерн Observer. То, что нужны действия по синхронизации, и непосредственный вызов методов формы не катит - это понятно. Но реализация формой интерфейса Listener... не знаю... по-моему, это весьма стандартный подход.
С учетом аспектов синхронизации, у меня есть один "слушатель"-адаптер, который синхронизирует вызовы методов Listener и передает их дальше по цепочке форме, но уже в потоке VCL.
Идея всех пассов в том, что там формы вообще может не быть... мало ли кто может "слушать" класс бизнес-логики.
Насчет посылки сообщения - спасибо, идея интересная. Поработаю над этим.


> У тебя в голове каша с "интерфейсами".
> Разберись с этой кашей.

Стараюсь. Вся жизнь - борьба с "кашей".


> Надеюсь, ты понимаешь что п/программа, будучи вызванной
> в некоем кодовом потоке, будет выполнена в контекте того
> же кодового потока.

Угу. А что, не заметно? :)

Еще раз всем спасибо.


Сергей М.   (2006-03-13 16:12:00) [5]


> Игорь Шевченко ©   (13.03.06 16:10) [8]


Остынь.
Нет никаких "наездов".


Игорь Шевченко   (2006-03-13 16:10:00) [6]

Сергей М. ©   (13.03.06 15:59) [6]

для наездов лучше найти другую аудиторию


Сергей М.   (2006-03-13 16:01:00) [7]


> Пономарев Андрей  


Надеюсь, ты понимаешь что п/программа, будучи вызванной в некоем кодовом потоке, будет выполнена в контекте того же кодового потока.


Сергей М.   (2006-03-13 15:59:00) [8]


> Пономарев Андрей   (13.03.06 15:17) [3]


У тебя в голове каша с "интерфейсами".
Разберись с этой кашей.


Игорь Шевченко   (2006-03-13 15:42:00) [9]


> . Соответственно, нитка бизнес-логики в нужные моменты вызывает
> те или иные методы Listener'a.


А это неверно. Нужно реализовывать этот интерфейс в посреднике, который будет заниматься Synchronize или иным способом оповещать VCL-форму в другом потоке, например, посылкой сообщения. Форма этот интерфейс реализовывать не должна.


Eraser   (2006-03-13 15:37:00) [10]


> Пономарев Андрей   (13.03.06 15:17) [3]

так параметры можно передавать либо через поля класса, либо через глобальные переменные.


Пономарев Андрей   (2006-03-13 15:17:00) [11]

Это-то понятно, но главным, пожалуй, недостатком Synchronize, применительно к данной задаче, является невозможность передать аргументы в функцию. А следовательно, весь интерфейс Listner'а сведется к

procedure UpdateView;

... печально.


Сергей М.   (2006-03-13 14:36:00) [12]


> через Synchronize(). Все работает


На то Synchronize() и придуман.


Сергей М.   (2006-03-13 14:32:00) [13]


> Попытка сделать showmessage в методе формы (реализующем
> операцию интерфейса) вызывает ошибку 'Canvas doesnt allow
> drawing'


Совершенно нормальное "явление".
ShowMessage() приводит к созданию и модальной визулизации формы.
Форма - VCL-объект.
Обращения к визуальным VCL-объектам в доп.потоках не допустимы.


Наверх

Титульная страница Поиск, карта сайта Написать письмо