Форум: "Основная";
Текущий архив: 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.041 c