![]() |
|
|
![]()
|
|
| Brodyaga |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Всем здравствуйте! Есть ли в С++ или MFC какой-нить аналог си шарповского InvokeRequired/BeginInvoke??
|
|||
|
||||
| Brodyaga |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Неужели никто не знает?! Другими словами мне нужно асинхронное выполнение какого либо метода.
|
|||
|
||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Асинхронное? В смысле выполнение не в момент вызова, а позже, но тоже в главном потоке? Тогда PostMessage какому-нибудь окну или приложению + соответствующий обработчик этого сообщения.
-------------------- ... |
|||
|
||||
| Brodyaga |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Наверное немного неправильно выразился... Вообще на си шарпе есть такая конструкция:
Сначала проверяем с помощью InvokeRequired, была ли вызвана функция Method из главного потока или нет, ежели нет, то вызываем её заново с тем же параметром но из главного потока. Вот мне надо такое же реализовать на обычном С или MFC... Как это сделать подскажите пожалуйста? |
|||
|
||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Т.е. некто вызывает функцию Method бог знает откуда, а тебе нужно, чтобы она гарантированно выполнялась в главном потоке, я правильно поняла?
Готового такого механизма нет, но можно воспользоваться тем фактом, что оконная функция (все обработчики) всегда выполняются в том потоке, которому принадлежит окно. Главный поток (если интерфейсных потоков несколько) - это поток, которому принадлежит главное окно. Т.е. чтобы гарантировать выполнение функции в главном потоке, нужно просто вызвать ее из какого-то обработчика главного окна. А инициировать вызов - послать какое-то юзеровское сообщение главному окну. Чтобы не парить мозги вызывающему коду, можно спрятать все это дело внутрь твоего класса:
Вызов Method из любого потка будет выглядеть как синхронный (потому что мы используем SendMessage); Этим можно воспользоваться, чтобы просто передать указатель на вашу строкe-аргумент в LPARAM - она гарантированно будет существовать в момент вызова. -------------------- ... |
|||
|
||||
| Brodyaga |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Этот способ я знаю, просто думал может есть готовый механизм... Ещё можно также переопределить оконную процедуру и в ней всю логику обрабатывать...
Но хотелось бы всё же, чтобы была такая же функция как BeginInvoke в С#... Первый параметр делегат на любую функцию(указатель) далее идёт любое количество параметров любого типа для функции на которую указывает делегат. Внутри себя BeginInvoke передаёт эти параметры в функцию делегата... Попытался реализовать такое в С++. Итак, что должна делать функция-аналог сишарповской BeginInvoke: 1.Принимать делегат(указатель) на любую функцию 2.Принимать любое количество параметров любых типов. 3.Передать указатель на делегат и все параметры через SendMessage в обработчик 4.Обработчик сообщения вызывает функцию на которую указывает делегат даже не зная, что это за функция 5.Обработчик сообщения передаёт в функцию на которую указывает делегат все переданные параметры через SendMessage Сделал делегат с общим базовым классом, который и передаёца в мой сишный вариант BeginInvoke. Но вот проблема... Как передать параметры через SendMessage и затем в обработчике сообщения их передать в функцию делегата, если набор параметров и их типы всегда разные??? |
|||
|
||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 87 Всего: 183 |
Для любого числа аргументов сделать и, так, чтобы это было удобно (т.е. с естественным синтаксисом), нельзя, да и не нужно. Основная проблема - переменный нужно где хранить, в параметры SendMessage можно упаковать только 2 инта или 2 указателя. Значит, нужна динамическая структура, где будут храниться переменные пока это необходимо. Другая проблема - тип переменной может быть любым, т.е. нужно обобщенное хранилище типа варианта. Я обычно использую boost::any. А проблема с разным числом параметров решается шаблонами. Я обычно ограничиваюсь 3-4, больше аргументов приличная функция использовать не должна. Я делала что-то подобное, но не для передачи управления между потоками, а для пересылки команд с аргументами через WM_COMMAND между модулями. Но принцип хранения-извлечения переменныйх можно использовать тот же. Если хочешь, могу дать код. -------------------- ... |
|||
|
||||
| Brodyaga |
|
||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Ну boost я не использую.. если использовать обобщённое хранилище типа вариант и передавать его через сендмесседж например сообщением WM_COPYDATA, то как я в обработчике узнаю какой вариант к какому типу мне преобразовывать при передаче параметров в функцию на которую указывает мой делегат?
Так я её и решил, так как делегат свой я и делал на основе шаблонов. Запихнул туда ещё один класс такого типа
ну вот чтото типа того.. тоесть для делегата с определённым набором параметров существует и определённый класс хранящий данные для функции! а общий класс для делегата выглядит примерно так template<TType> class IDelegate { TType Invoke(BaseDataObject); } Но ещё одна проблема заключается в передаче через сенд мессадж указателя на свой делегат, так как ЕДИНОГО базового класса для него нет.. вернее есть, но так как используюца шаблоны он всегда разный... и в обработчике сообщения посланного сендмессаджом не ясно к какому типу преобразовывать делегат толи к IDelegate<void> а толи IDelegate<int> к примеру... а хочеца ЛЮБОЙ делегат просто преобразовать к типу IDelegate и вызвать метод на который делегат указывает ,как в с#... Как нить можно сделать единный базовый класс??? в с# то наверное делегаты внутри реализованы таким образом, что в базовом классе у функции возвращаемое значение типа Object ;) а там всё object |
||||||
|
|||||||
| Brodyaga |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 599 Регистрация: 19.1.2008 Репутация: нет Всего: 2 |
Вообщем ладно.. Наверное так нельзя сделать, да и не к чему. Остановлюсь на варианте, о котором думал сначала.. Тоесть обойдусь SendMessage. Тема закрыта.
|
|||
|
||||
![]()
|
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Visual C++/MFC/WTL | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |