Многопоточность WTL, несколько интерфейсов и библиотек

У меня есть основной поток, который отображает интерфейс, в другом потоке, созданном из основного потока до отображения основного интерфейса, я последовательно создаю два других окна: я создаю первое окно:

    CWarningDlg warnDlg;
    warnDlg.Create(NULL);
    warnDlg.ShowWindow(SW_SHOW);
    warnDlg.BringWindowToTop();
    CMessageLoop _Loop ;

    if(_MyAppModule.AddMessageLoop(&_Loop))
    {
        nRet = _Loop.Run();
        _MyAppModule.RemoveMessageLoop();
    }
    warnDlg.DestroyWindow();
    if (nRet == SOME_VALUE)
    {
       doSomethingElse();
    }

Сделайте что-нибудь еще:

 CActionDlg actDlg;
    actDlg.Create(NULL);
    actDlg.ShowWindow(SW_SHOW);
    actDlg.BringWindowToTop();
    CMessageLoop _Loop ;

    if(_MyAppModule.AddMessageLoop(&_Loop))
    {
        CreateAnObject(); //this also launches an object Specific Worker Thread
        nRet = _Loop.Run();
        _MyAppModule.RemoveMessageLoop();
    }

Функция CreateAnObject вызывает некоторые функции из «ComplexObject.DLL», которые создают сложный объект, который содержит идентификатор THREAD потока, вызвавшего функцию CREATION, он получает его с помощью ::GetCurrentThreadId(); , при создании этого сложного объекта GetCurrentThreadId() возвращает идентификатор ВТОРОГО ПОТОКА, что ХОРОШО. Теперь в моем CActionDialog я получаю уведомления от этого объекта с помощью ::SendMessage(), функция SendMessage вызывается из рабочего потока, специфичного для только что созданного сложного объекта. Когда я получаю эти уведомления, мне нужно получить доступ к некоторым из этих сложных значений объектов, для этого я вызываю некоторые другие функции из "ComplexObject.DLL", которые проверяют с помощью функции ::GetCurrentThreadId(), что идентификатор вызывающего потока совпадает с идентификатор потока, который создал этот сложный объект. Эта проверка не работает для меня, потому что функции вызываются с использованием идентификатора потока MAIN THREAD, который имеет графический интерфейс основного интерфейса. Почему это? Я не понимаю! (Надеюсь, я успешно объяснил себя).


person AlexandruC    schedule 20.08.2013    source источник


Ответы (1)


Проблема, с которой вы столкнулись, по крайней мере, из вашего описания, заключается в том, что какой бы внешний API вы ни использовали через CreateAnObject, он ограничивает его дальнейшее использование потоком создания. Принимая это как есть, вы ограничены вызовами только из потока создания. Всякий раз, когда вашему коду, работающему в других объявлениях, в том числе в хостинге потоков CWarningDlg, необходимо обратиться к этому API, вам нужно передать вызов потоку CActionDlg и продолжить оттуда.

Синхронизация может быть SendMessage, которую вы уже сделали, или чем-то более безопасным, например PostMessage с уведомлением о завершении события/сообщения.

person Roman R.    schedule 20.08.2013
comment
Но разве недостаточно того, что CActionDialog работает во втором потоке? Он является локальным для функции CreateAnObject, из которой я создаю этот внешний объект. Разве запуск цикла и создание экземпляра CActionDialog в этом потоке не означает, что я работаю из этого потока? - person AlexandruC; 20.08.2013
comment
SendMessage через магию передает вызовы в поток, в котором было создано окно. Событие, если вы используете указатели оттуда напрямую, это будет другой поток. Я полагаю, это та часть, которая смущает вас. Однажды переключившись на другой поток, вы не переключились обратно, а затем столкнулись с несоответствием потока. - person Roman R.; 20.08.2013
comment
разве DispatchMessage не вызывается из _Loop.Run(), который находится в потоке создания сложных объектов? - person AlexandruC; 20.08.2013
comment
Вы пишете, что видите основной поток в действии, а там видите несоответствие ID. Вы должны иметь возможность проверять стек вызовов оттуда и видеть, где вы находитесь, особенно. какое сообщение вы сейчас обрабатываете. И это будет окно основного потока, а не CActionDlg. - person Roman R.; 20.08.2013
comment
Разве этот идентификатор потока не должен быть идентификатором потока 2? CMessageLoop изменяет это, вызывая ::DispatchMessage ? - person AlexandruC; 20.08.2013
comment
Запускается ли CACtionDialog в другом «потоке» или как? - person AlexandruC; 20.08.2013
comment
В моем сценарии я вообще не должен видеть main... Я не имею к этому никакого отношения... все, что я делаю, это во втором потоке, и тем не менее... CActionDialog работает с идентификатором потока основного потока. - person AlexandruC; 20.08.2013
comment
Из вашего описания вы не должны видеть основную ветку, но видите, что на самом деле находитесь в ней. Значит, что-то работает не так, как вы ожидаете. Итак, вы смотрите на стек вызовов, чтобы понять, почему вы находитесь в потоке, в котором не должны быть. Как только вы столкнулись с несоответствием потоков, вам нужно остановиться и оглянуться назад, чтобы увидеть, как вы туда попали. - person Roman R.; 20.08.2013
comment
Да, это правда, я не должен видеть основной поток... если нет поведения CMessageLoop, о котором я не знаю... это тоже с высокой вероятностью... сейчас я смотрю на стек... - person AlexandruC; 20.08.2013
comment
Итак, у вас сложилось впечатление, что вы создаете материал на CreateAnObject во вторичном потоке. Теперь вы обнаружили, что это было в основной теме. - person Roman R.; 20.08.2013
comment
Когда я создаю объект, функция, которая создает вызовы ::GetCurrentThreadID.. и возвращает идентификатор вторичного потока... но CActiondDialog отправляется из цикла MAin... имеет ли это отношение к тому, где я загружаю библиотеки. .. ? - person AlexandruC; 20.08.2013
comment
Я создаю объект из второго потока... ::GetCurrentThreadID утверждает, что... после вызова CreateAnObject() обработчик CACtionDialog вызывается из неправильного цикла сообщений (основного) - person AlexandruC; 20.08.2013
comment
Я полный NOOB... Я уже создавал такой же диалог, используя этот ресурс в Main... вот почему я получал там сообщения... - person AlexandruC; 20.08.2013
comment
Спасибо .. и извините, что отвлек вас от моего .. невнимания. - person AlexandruC; 20.08.2013
comment
Эй, вот еще один, если у вас есть время stackoverflow.com /вопросы/18365924/ - person AlexandruC; 22.08.2013