Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема с событиями в com, sleep блокирует вызов событий 
:(
    Опции темы
al_capone
Дата 25.2.2009, 18:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 14.7.2007

Репутация: нет
Всего: нет



Добрый вечер.
Cразу хочу предупредить, что я новичок в com.
Есть ActiveX c ThreadingModel=Apartment. Он может получать данные из сети, а прочитанные данные возвращать через events.
Я написал функцию которую крутит отдельный поток:
Код


int MyClass::grabTh(void* pParam)
{
    MyClass* pThis = static_cast<MyClass*>(pParam);
    //init COM and ATL
    CATLinitializer initObj; 
        
    try
    {
        //instance VWDataAccessCtrl object
        IVWDataAccessCtrlPtr pDataAcces(CLSID_VWDataAccessCtrl);
        
        //create and connect event handler to  source
        CVWEventsProxy eventsProxy(pDataAcces, pThis);

        //connecting to host
        pDataAcces->put_Url(CComBSTR("192.168.0.6:5002"));
        pDataAcces->put_Blocking(FALSE);
        HRESULT hr = pDataAcces->Connect();

        //TODO: conditional variable wait
        MessageBox(0,"mess","mess",0);
        pDataAcces->Disconnect();
    }
    catch (const _com_error& e)
    {
        
    }

    return 0;
}




тут создается объект COM от которого идут события (VWDataAccessCtrl ), создается объект CVWEventsProxy отнаследованный от IDispEventImpl, и в конструкторе он еще подключается к pDataAcces. Т.е. события должны приходить в eventsProxy.

Я столкнулся с двумя проблемами в этом коде:
1)Когда эта функция один раз отрабатывает, поток уничтожается, когда же я заново создаю поток и выполняется этот код, при инициализации COM (CoInitialize(NULL)) в дебаге выскакивает противный assert вот в этом месте

Код

    CAtlModule() throw()
    {
        // Should have only one instance of a class 
        // derived from CAtlModule in a project.
        ATLASSERT(_pAtlModule == NULL);



после него CoInitialize возвращает S_OK. Соответственно в релизе никаких нареканий в работе нет. Что мне с этим делать?

2)Основная проблема: Если я уберу MessageBox и поставлю sleep, например, или буду делать что то левое, то события не вызываются.Насколько я понял, когда я создаю “STA поток”, то в этом потоке выполняется и обработчик сообщений (оконные сообщения) для обектов com (насколько я понял events вызываются в ответ на сообщения). Когда же я делаю sleep() (или любое другое действие). Поток приостанавливается и обработчик соответственно тоже, поэтому не работает. (не вдумываетесь в последние 2 предложения)

Если вам лень объяснять что и почему, буду рад просто ссылке, но именно по теме.
Спасибо за внимание.
PM MAIL   Вверх
jonie
Дата 26.2.2009, 09:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

Репутация: 5
Всего: 118



как я понимаю ситуацию: у вас есть блокирующий вызов accept(), и после коннекта вы делаете новый поток, куда пропихиваете COMобъект MyClass через параметр pParam. Так делать нельзя - у вас MyClass создан в потоке не принадлежащему апартаменту где создан объект (у вас же STA, а не MTA => один поток на апартамент). Для проброса нужно использовать маршалинг(CoMarshal чета тут функцию) (или, если вы точно уверены что делаете, и у вас inproc сервер, тогда можно GIT использовать (появилось в win2000 вроде) (и получать указатель уже через cookie)) - гугл по слову RegisterInterfaceInGlobal.

http://www.compdoc.ru/prog/cpp/com/ch5/ch510.shtml


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
al_capone
Дата 26.2.2009, 09:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 14.7.2007

Репутация: нет
Всего: нет



нет, извиняюсь за весьма непонятный код, нужно было упростить код и все не нужное отсеять. Наверное слово proxy вас отвлекает от истины. Ситуация такая: чтобы не делать весьма непонятные мне вещи типа маршалинга, я сделал отдельный поток для работы с ком объектом, в этом потоке я его создаю, потом подключаюсь к событиям, потом вызываю connect com объекта. с этого момента данные должны приходить через события.  через некоторое время  делается дисконект в этом же потоке, и и ком объект уничтожается. т.е. с объектом работает только один поток и только одна функция (код которой в первом комменте). 
PM MAIL   Вверх
xvr
Дата 26.2.2009, 15:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 8
Всего: 223



По п1 - что такое CATLinitializer ? Сдается мне, что оно должно быть в main.
По п2 нужно сделать цикл обработки сообщений (GetMessage/ProcessMessage) вместо MessageBox (или отказаться от ATM, сделать например FreeThreaded, но может и не помочь)

PM MAIL   Вверх
al_capone
Дата 26.2.2009, 15:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 14.7.2007

Репутация: нет
Всего: нет



1)вот
Код

    
       class CATLinitializer : public boost::noncopyable
    {
    public:
        CATLinitializer();
        ~CATLinitializer();

    private:
        HRESULT m_hrCOM;
        HRESULT m_hrATL;
        CComModule _Module;
    };


/////////////////////////////////////////////////////
    CATLinitializer::CATLinitializer() :
    m_hrCOM(S_FALSE),
    m_hrATL(S_FALSE)
{
    m_hrCOM = CoInitialize(NULL);
    assert(!FAILED(m_hrCOM));

    m_hrATL = _Module.Init(NULL, GetModuleHandle(NULL));
    assert(!FAILED(m_hrATL));
}

////////////////////////////////////////////////////////
CATLinitializer::~CATLinitializer()
{
    if (SUCCEEDED(m_hrATL))
    {
        _Module.Term();
    }

    if (SUCCEEDED(m_hrCOM))
    {
        CoUninitialize();
    }
}


2)а можно пример как сделать обработчик сообщений? просто смотри, у меня это все происходит в длл, причем в таком что там нет ни mfc ни com ни atl. Это единственная функция где используется что то такое.
PM MAIL   Вверх
xvr
Дата 26.2.2009, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 8
Всего: 223



1) Строка 22 (m_hrATL = _Module.Init(NULL, GetModuleHandle(NULL));) здесь лишняя - ее надо выполнить только 1 раз на всю программу, а не каждый раз на каждый thread
2) Обработчик совершенно стандартный:
Код

    MSG msg;

    while(GetMessage(&msg,NULL,0,0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

Цитата

просто смотри, у меня это все происходит в длл, причем в таком что там нет ни mfc ни com ни atl. Это единственная функция где используется что то такое.
Этот цикл нужен для самой системы COM, ни mfc ни atl здесь не при чем. А COM у тебя используется - ты же event'ы через eventsProxy хочешь получать? А рассылает их как раз COM

PM MAIL   Вверх
al_capone
Дата 26.2.2009, 20:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 14.7.2007

Репутация: нет
Всего: нет



ок, большое спасибо, работает!!! основная проблема решена.
Теперь выявилась еще одна проблема, компонента работает нестабильно, после первого фрейма уходит в нирвану, потом в output вылезают ошибки типа тайм-аут сработал. Если этот самый код поместить в mfc exe (например при нажатии кнопки чтобы выполнялось все) то так работает отлично. Я знаю что информации явно недостаточно но соображения есть где копать?
еще раз, спасибо!

PM MAIL   Вверх
xvr
Дата 26.2.2009, 21:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 8
Всего: 223



Цитата(al_capone @ 26.2.2009,  20:06)
Теперь выявилась еще одна проблема, компонента работает нестабильно, после первого фрейма уходит в нирвану, потом в output вылезают ошибки типа тайм-аут сработал. Если этот самый код поместить в mfc exe (например при нажатии кнопки чтобы выполнялось все) то так работает отлично. Я знаю что информации явно недостаточно но соображения есть где копать?

Причин может быть вагон и маленькая тележка  smile  Например multithread проблемы - синхронизация и разделение ресурсов
Нужна более подробная информация о программе
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: COM/DCOM/ActiveX/ATL/CORBA | Следующая тема »


 




[ Время генерации скрипта: 0.0993 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.