![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
"Нити" и 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-объектам в доп.потоках не допустимы.