Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2006.04.16;
Скачать: [xml.tar.bz2];

Вниз

"Нити" и 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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.037 c
6-1136026685
ezorcist
2005-12-31 13:58
2006.04.16
Настлоение строк


15-1143186047
оЛиневод
2006-03-24 10:40
2006.04.16
Как хранится файл на диске


15-1143053426
Зм1й
2006-03-22 21:50
2006.04.16
Xp Home


9-1117512796
XProger
2005-05-31 08:13
2006.04.16
Delphi 4k DEMO


1-1141495041
lookin
2006-03-04 20:57
2006.04.16
Как исключить свойство из компонента





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский