Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.04.16;
Скачать: CL | DM;

Вниз

"Нити" и showmessage   Найти похожие ветки 

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

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

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

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

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

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

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

Спасибо.


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


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


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


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


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


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


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

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

procedure UpdateView;

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


 
Eraser ©   (2006-03-13 15:37) [4]


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

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


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


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


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


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


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


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


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


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


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


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

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

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


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


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


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


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

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


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

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


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

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


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

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


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

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

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


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

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


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


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


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

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


> Но никто не мешает реализовать интерфейс в классе-посреднике,
>  не привязанном к 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:44) [13]

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


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


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

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


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


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



Страницы: 1 вся ветка

Текущий архив: 2006.04.16;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.03 c
2-1144136085
Klopan
2006-04-04 11:34
2006.04.16
Copy


3-1140342760
parademon
2006-02-19 12:52
2006.04.16
Как получить доступ к TRemoteDataModule


15-1143125776
ZeFiR
2006-03-23 17:56
2006.04.16
Преобразование картинки в ASCII символы


15-1143440491
Ega23
2006-03-27 10:21
2006.04.16
С Днём рождения! 26 марта


15-1143353614
Parus
2006-03-26 10:13
2006.04.16
В низу экрана, где "Пуск"...