MFC. Сообщения. Взаимодействие классов в потоке.
От: Genco  
Дата: 18.02.12 00:39
Оценка:
Приветствую всех участников!

Возможно, вопрос самоочевиден, но хелы, гайды и MSDN не помогли.
Возникла у меня не очень понятная проблема по основам, ответ на которую не находится ну никак.
Что хочу/нужно: создать в программе отдельный от основного поток, там будут работать 2 класса. У одного будет 1 экземпляр, ожидающий сообщения, у другого — куча экземпляров, их отсылающих. Вроде бы ничего сверхъестественного, но...
class CContext: public CWnd
{
private:
           //тут всякое...
    int id_counter;
protected:
    // (AFX_MSG_MAP(CContext)
    afx_msg int OnRecalc(TMSG *msg);
    //{(AFX_MSG_MAP)

    //тут всякое...
    DECLARE_MESSAGE_MAP()  //!!!
public:
    CContext(void): CWnd() { id_counter=0; }
            //тут всякое...
    ~CContext(void);
};

Это такой вот класс (не важно, что в нем напихано), пришлось наследоваться от CWnd, чтоб слушать сообщения. В нем есть карта сообщений (приписал в реализации):
BEGIN_MESSAGE_MAP(CContext, CWnd)
// (AFX_MSG_MAP(CContext)
    ON_KR_RECALC(OnRecalc)
    //ON_REGISTERED_MESSAGE(KR_RECALC,OnSample)
//{(AFX_MSG_MAP)
END_MESSAGE_MAP()

Тоже стандартно. Далее хитрее — класс, который будет что-то слать, передавая инфу через lParam:
#define RECALC_TAG _T("WAKEUP")
//Ерунда ниже, кстати, рабочая, взято с rsdn
#define ON_KR_RECALC(memberFxn) \
{ KR_RECALC, 0, 0, 0, AfxSig_is, (AFX_PMSG)(AFX_PMSGW) \
    (int (CWnd::*)(TMSG*))(memberFxn) },
//----------------------------------------------------

typedef struct MyMSG
{
    //бла-бла
} TMSG;

const int dt=700;

class KR_Object
{
    friend class CContext;
protected:
    int ID;
    CContext *context;
    void send_event(int dest, UINT span=dt);
public:
    virtual void do_job()=0;     //да, я от него наследуюсь по-всякому
    virtual void wakeup();     //не суть, что это всё
    void receive_event(TMSG);
};

//бла-бла
static const UINT NEAR KR_RECALC = ::RegisterWindowMessage(RECALC_TAG);

Оставил везде в приводимом самое основное, показать структуру моей "поделки", меньше не получится без потери смысла.
Непосредственно с самой посылкой всё вообще нехорошо, есть куча способов по идее, и ни один не работает((
SendMessage()/PostMessage() — неизвестен дескриптор, не катит
context->SendMessage() — внутри класса дескриптор невалидный, опять облом.
PostThreadMessage() — главная надежда, отсылка всему потоку, шлю, узнавая ID текущего потока и получаю облом.

CContext не реагирует, я замучался. Получается, что создавать полноценное окно мне не нужно, а вот обмениваться сообщениями, не вешая интерфейс (т.е. в отдельном потоке, где вся логика) — необходимо.

У кого есть идеи — помогите, пожалуйста, советом: что-я-делаю-не-так??
Re: MFC. Сообщения. Взаимодействие классов в потоке.
От: lxa http://aliakseis.livejournal.com
Дата: 18.02.12 08:56
Оценка:
Не в этом ли дело? (Взято из MSDN)

The thread to which the message is posted must have created a message queue, or else the call to PostThreadMessage fails. Use one of the following methods to handle this situation.

Call PostThreadMessage. If it fails, call the Sleep function and call PostThreadMessage again. Repeat until PostThreadMessage succeeds.

Create an event object, then create the thread. Use the WaitForSingleObject function to wait for the event to be set to the signaled state before calling PostThreadMessage. In the thread to which the message will be posted, call PeekMessage as shown here to force the system to create the message queue.
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE)
Set the event, to indicate that the thread is ready to receive posted messages.

Re[2]: MFC. Сообщения. Взаимодействие классов в потоке.
От: Genco  
Дата: 19.02.12 20:47
Оценка:
Хм, спасибо.

Немного поковырялся, получается, что класс-слушатель должен постоянно сидеть на PeekMessage(). Т.е. руками мне придется собрать некое подобие цикла обработки сообщений, что полностью блокирует прочий код, ну по крайней мере затруднит возможность делать что-то ещё.

Т.е. карта сообщений не решает проблему? А вообще разумно ли обмениваться именно через виндовские механизмы, мб настоять на отказе от затеи?
Re: MFC. Сообщения. Взаимодействие классов в потоке.
От: AlexGin Беларусь  
Дата: 20.02.12 07:24
Оценка:
Здравствуйте, Genco, Вы писали:

G>static const UINT NEAR KR_RECALC = ::RegisterWindowMessage(RECALC_TAG);


G>Оставил везде в приводимом самое основное, показать структуру моей "поделки", меньше не получится без потери смысла.

G>Непосредственно с самой посылкой всё вообще нехорошо, есть куча способов по идее, и ни один не работает((
G> SendMessage()/PostMessage() — неизвестен дескриптор, не катит
G> context->SendMessage() — внутри класса дескриптор невалидный, опять облом.
G> PostThreadMessage() — главная надежда, отсылка всему потоку, шлю, узнавая ID текущего потока и получаю облом.

G>CContext не реагирует, я замучался. Получается, что создавать полноценное окно мне не нужно, а вот обмениваться сообщениями, не вешая интерфейс (т.е. в отдельном потоке, где вся логика) — необходимо.


G> У кого есть идеи — помогите, пожалуйста, советом: что-я-делаю-не-так??


Если Вы применяете АПИ-шную функцию RegisterWindowMessage, то почему в карте обработки сообщений не применили ON_REGISTERED_MESSAGE?

P.S. А упростить карту обработки сообщений (хотя бы для пробы) применяя ON_MESSAGE (если сообщение было отправлено SendMessage()/PostMessage())
или же ON_THREAD_MESSAGE, если была отправка через PostThreadMessage() — так пробовали?

Пример1:
В файле *.cpp
BEGIN_MESSAGE_MAP(CMyApp, CWinApp)
    ...
    ON_THREAD_MESSAGE(ID_APP_MESSAGE,OnAppMessage)
        ...
END_MESSAGE_MAP()

...............
void CMyApp::OnAppMessage(WPARAM wParam, LPARAM lParam)
{
    ...
}


В файле *.h — дать дефинацию для OnAppMessage

Пример2:
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
        ...
    ON_MESSAGE(MYWN_TOOLBAR_COMBO_CHANGE, OnToolBarComboChange)
        ...
END_MESSAGE_MAP()    

...............
long CMainFrame::OnToolBarComboChange(WPARAM wParam, LPARAM lParam)
{
        ...
    return 0L;
}


В файле *.h — дать дефинацию для OnToolBarComboChange
Re[3]: MFC. Сообщения. Взаимодействие классов в потоке.
От: AlexGin Беларусь  
Дата: 20.02.12 07:31
Оценка:
Здравствуйте, Genco, Вы писали:

G> Хм, спасибо.


G>Немного поковырялся, получается, что класс-слушатель должен постоянно сидеть на PeekMessage(). Т.е. руками мне придется собрать некое подобие цикла обработки сообщений, что полностью блокирует прочий код, ну по крайней мере затруднит возможность делать что-то ещё.


G>Т.е. карта сообщений не решает проблему? А вообще разумно ли обмениваться именно через виндовские механизмы, мб настоять на отказе от затеи?


Возможно, эти же идеи можно реализовать и через сокеты. Но может стоит попробовать в карте сообщений применить ON_MESSAGE или ON_THREAD_MESSAGE (как я Вам уже писал здесь). Если уже ON_MESSAGE/ON_THREAD_MESSAGE не прокатит по каким-либо причинам, тогда через сокеты.
Re: MFC. Сообщения. Взаимодействие классов в потоке.
От: RSATom Россия  
Дата: 20.02.12 09:40
Оценка:
как то сложно все...

Советы:
1. Cообщения слать через SendMessage
2. В рабочую нить передавать _только_ HWND окна которому хотим посылать сообщения
3. Сначала нужно добится отсылки/получения сообщений в рамках одной нити, а затем переходить к нескольким нитям, где все будет абсолютно идентичтно за исключением того что в рабочую нить нужно будет протащить HWND окна при запуске нити.
Re[2]: MFC. Сообщения. Взаимодействие классов в потоке.
От: RSATom Россия  
Дата: 20.02.12 09:43
Оценка:
Здравствуйте, RSATom, Вы писали:

RSA>как то сложно все...


RSA>Советы:

RSA>1. Cообщения слать через SendMessage
RSA>2. В рабочую нить передавать _только_ HWND окна которому хотим посылать сообщения
RSA>3. Сначала нужно добится отсылки/получения сообщений в рамках одной нити, а затем переходить к нескольким нитям, где все будет абсолютно идентичтно за исключением того что в рабочую нить нужно будет протащить HWND окна при запуске нити.

на чистом Win32 API концепцию можно посмотреть вот здесь (класс EventSystemProxyWnd)
Re[3]: MFC. Сообщения. Взаимодействие классов в потоке.
От: RSATom Россия  
Дата: 20.02.12 09:55
Оценка:
Здравствуйте, RSATom, Вы писали:

RSA>Здравствуйте, RSATom, Вы писали:


RSA>>как то сложно все...


RSA>>Советы:

RSA>>1. Cообщения слать через SendMessage
RSA>>2. В рабочую нить передавать _только_ HWND окна которому хотим посылать сообщения
RSA>>3. Сначала нужно добится отсылки/получения сообщений в рамках одной нити, а затем переходить к нескольким нитям, где все будет абсолютно идентичтно за исключением того что в рабочую нить нужно будет протащить HWND окна при запуске нити.

RSA>на чистом Win32 API концепцию можно посмотреть вот здесь (класс EventSystemProxyWnd)

Хотя стоп! Я правильно понял, что осылать и получать сообщения нужно в окнах которые будут находится в одной рабочей нити?
Re[4]: MFC. Сообщения. Взаимодействие классов в потоке.
От: Genco  
Дата: 07.03.12 21:53
Оценка:
Здравствуйте, AlexGin, Вы писали:

AG>Здравствуйте, Genco, Вы писали:


G>> Хм, спасибо.


G>>Немного поковырялся, получается, что класс-слушатель должен постоянно сидеть на PeekMessage(). Т.е. руками мне придется собрать некое подобие цикла обработки сообщений, что полностью блокирует прочий код, ну по крайней мере затруднит возможность делать что-то ещё.


G>>Т.е. карта сообщений не решает проблему? А вообще разумно ли обмениваться именно через виндовские механизмы, мб настоять на отказе от затеи?


AG>Возможно, эти же идеи можно реализовать и через сокеты. Но может стоит попробовать в карте сообщений применить ON_MESSAGE или ON_THREAD_MESSAGE (как я Вам уже писал здесь). Если уже ON_MESSAGE/ON_THREAD_MESSAGE не прокатит по каким-либо причинам, тогда через сокеты.


Так...извиняюсь, что пропал на середине обсуждения, просто прояснилась суть задачи.
Ерунда оказалась в том, что если изначально задача была собрать описанное _совсем_ руками (без внешних к языку решений), то потом оказалось, что всякие наследования от CWnd сюда же и относятся.

Обработчики, как выяснилось, ловят всё — просто совместить в рабочем потоке НЕ зависающее окно, циклическую обработку данных и всё это скрыть — это совсем плохая идея. По-умному опрошеный гугл выдал message-only windows, вот что пытался сделать. Плюс повозился, чтобы поток, где оно висит, не закрывался сразу...но это костыль какой-то, такое окно и в общем потоке хорошо пашет благодаря сообщениям.
Re[4]: MFC. Сообщения. Взаимодействие классов в потоке.
От: Genco  
Дата: 07.03.12 22:18
Оценка:
Здравствуйте, RSATom, Вы писали:

RSA>Здравствуйте, RSATom, Вы писали:


RSA>>Здравствуйте, RSATom, Вы писали:


RSA>>>как то сложно все...


RSA>>>Советы:

RSA>>>1. Cообщения слать через SendMessage
RSA>>>2. В рабочую нить передавать _только_ HWND окна которому хотим посылать сообщения
RSA>>>3. Сначала нужно добится отсылки/получения сообщений в рамках одной нити, а затем переходить к нескольким нитям, где все будет абсолютно идентичтно за исключением того что в рабочую нить нужно будет протащить HWND окна при запуске нити.

RSA>>на чистом Win32 API концепцию можно посмотреть вот здесь (класс EventSystemProxyWnd)

RSA>Хотя стоп! Я правильно понял, что осылать и получать сообщения нужно в окнах которые будут находится в одной рабочей нити?

Нет, нитей сказали сделать именно 2 и вот почему: идея была, оказывается, сделать класс-диспетчер совершенно независимый, который сидит и обрабатывает в непрерывном режиме нечто (взаимодействие между другими объектами), при этом от окна отнаследоваться почему-то некомильфо. Ну, естественно, такой класс запускает где-либо цикл и его приходится выносить в отдельный поток — в основном только остается интерфейс и отрисовка (по таймеру).
Как только понял — оставалось синхронизацию наладить, да грамотно предусмотреть механизм, чтоб рабочий поток на команды извне реагировал, дело техники, в принципе.

А вот за ссылку большое спасибо! Изрядно помогла по смежной тематике,как продолжение той ерунды, про которую спрашивал.

Ну и спасибо всем, кто вообще откликнулся на топик, приятный контраст с рядом других программистских форумов.
Re: MFC. Сообщения. Взаимодействие классов в потоке.
От: MasterZiv СССР  
Дата: 07.03.12 22:31
Оценка:
G> Что хочу/нужно: создать в программе отдельный от основного поток, там будут работать 2 класса. У одного будет 1 экземпляр, ожидающий сообщения, у другого — куча экземпляров, их отсылающих. Вроде бы ничего сверхъестественного, но...

Остановись метаться туда-сюда, реализовывая всё это, и объясни, не что ты хочешь сделать, а зачем тебе это нужно.
Re[5]: MFC. Сообщения. Взаимодействие классов в потоке.
От: MasterZiv СССР  
Дата: 08.03.12 07:24
Оценка: +1
> Нет, нитей сказали сделать именно 2 и вот почему: идея была, оказывается,
> сделать класс-диспетчер совершенно независимый, который сидит и обрабатывает в
> непрерывном режиме нечто (взаимодействие между другими объектами), при этом от
> окна отнаследоваться почему-то некомильфо. Ну, естественно, такой класс
> запускает где-либо цикл и его приходится выносить в отдельный поток — в основном
> только остается интерфейс и отрисовка (по таймеру).

Сообщения Windows привязаны к определённому потоку, их нельзя обрабатывать в
любом произвольном потоке. Сообщения не являются также контекстно-независимыми,
они часто ссылаются на информацию, которая лежит где-то вовне, и поэтому доступ
к сообщениям в разных потоках будет требовать синхронизацию доступа к данным.

В общем, ещё раз, объясни детаолько ЗАЧЕМ это надо, я подозреваю, что
то, что вы хотите делать, делать в принципе нельзя.
Posted via RSDN NNTP Server 2.1 beta
Re[4]: MFC. Сообщения. Взаимодействие классов в потоке.
От: MasterZiv СССР  
Дата: 08.03.12 07:29
Оценка: 1 (1)
> RSA>>1. Cообщения слать через SendMessage

SendMessge между разными потоками синхронизируется дополнительно.
Нужно использовать либо PostMessage, либо SendMessageTimeout.


> RSA>>3. Сначала нужно добится отсылки/получения сообщений в рамках одной нити, а

> затем переходить к нескольким нитям, где все будет абсолютно идентичтно за
> исключением того что в рабочую нить нужно будет протащить HWND окна при запуске
> нити.

Наоборот, всё совсем по-разному. Посылка сообщения (SendMessage) ---строго
синхронный процесс. Посылка сообщения другому потоку -- асинхронный.
Поэтому Windows синхронизирует при этом потоки, посылающий и принимающий.
Тут можно очень легко нарваться на deadlock-и и положить приложение.
Posted via RSDN NNTP Server 2.1 beta
Re: MFC. Сообщения. Взаимодействие классов в потоке.
От: okman Беларусь https://searchinform.ru/
Дата: 08.03.12 10:23
Оценка: 2 (1)
Здравствуйте, Genco, Вы писали:

G> Что хочу/нужно: создать в программе отдельный от основного поток, там будут работать 2 класса. У одного будет 1 экземпляр, ожидающий сообщения, у другого — куча экземпляров, их отсылающих. Вроде бы ничего сверхъестественного, но...

G>...
G>Это такой вот класс (не важно, что в нем напихано), пришлось наследоваться от CWnd, чтоб слушать сообщения. В нем есть карта сообщений (приписал в реализации):
G>...

G> У кого есть идеи — помогите, пожалуйста, советом: что-я-делаю-не-так??


Переусложняете.

GUI-поток и рабочий поток нужно держать в изоляции друг от друга, а здесь
рабочий поток построен на оконной процедуре, а еще связан с определениями из MFC.
Плохо это, так как код рабочего потока получится как минимум непереносимым, и
как только будет меняться GUI-часть, это повлечет за собой необходимость
изменений и в нем тоже.

Это во-первых. Во-вторых, вместо очереди оконных сообщений лучше взять что-нибудь
вроде std::queue, и использовать ее как контейнер данных для обоих классов.
Когда главное окно передает сообщение первому классу — оно просто создает объект message и
добавляет его в конец первой очереди. Выборка сообщений потоком может быть организована
по-разному, в зависимости от специфики задачи. Когда один из классов потока нуждается в
передаче сообщения главному окну, он просто ставит message в свою очередь и сигнализирует
главному окну каким-нибудь приватным оконным сообщением через PostMessage. Вот и вся механика.
Код получится в разы прозрачнее и гибче. Очереди, само собой, должны быть потокобезопасными,
то есть, EnterCriticalSection на входе и LeaveCriticalSection на выходе.

И уберите эти "ON_KR_RECALC", "KR_Object" и "const int dt=700;" — глаза режет.
Re[6]: MFC. Сообщения. Взаимодействие классов в потоке.
От: Genco  
Дата: 08.03.12 12:41
Оценка:
Здравствуйте, MasterZiv, Вы писали:


>> Нет, нитей сказали сделать именно 2 и вот почему: идея была, оказывается,

>> сделать класс-диспетчер совершенно независимый, который сидит и обрабатывает в
>> непрерывном режиме нечто (взаимодействие между другими объектами), при этом от
>> окна отнаследоваться почему-то некомильфо. Ну, естественно, такой класс
>> запускает где-либо цикл и его приходится выносить в отдельный поток — в основном
>> только остается интерфейс и отрисовка (по таймеру).

MZ>Сообщения Windows привязаны к определённому потоку, их нельзя обрабатывать в

MZ>любом произвольном потоке. Сообщения не являются также контекстно-независимыми,
MZ>они часто ссылаются на информацию, которая лежит где-то вовне, и поэтому доступ
MZ>к сообщениям в разных потоках будет требовать синхронизацию доступа к данным.

MZ>В общем, ещё раз, объясни детаолько ЗАЧЕМ это надо, я подозреваю, что

MZ>то, что вы хотите делать, делать в принципе нельзя.

Ниже участник очень точно описал, что примерно требовалось.
Идея такая: имеется N объектов, они обмениваются между собой сообщениями, по приходу которых выполняют некие действия. В простейшем случае — шлют сообщение сами себе регулярно. Один главный класс хранит пул объектов и пул наступающих событий, рассылая сообщения адресатам и вообще забирая на себя всю коммуникацию.

Ключевой момент — это то, что слово "сообщения" я понял буквально (сказано — сделано), потому долго пытался прикрутить к классу-диспетчеру навеску с виндовыми обработчиками, в рабочем потоке они тормозили. Мне постучали по репе и сказали сделать по-людски (ниже как раз описана идея).
Re[2]: MFC. Сообщения. Взаимодействие классов в потоке.
От: Genco  
Дата: 08.03.12 12:59
Оценка:
Здравствуйте, okman, Вы писали:

O>Здравствуйте, Genco, Вы писали:


G>> Что хочу/нужно: создать в программе отдельный от основного поток, там будут работать 2 класса. У одного будет 1 экземпляр, ожидающий сообщения, у другого — куча экземпляров, их отсылающих. Вроде бы ничего сверхъестественного, но...

G>>...
G>>Это такой вот класс (не важно, что в нем напихано), пришлось наследоваться от CWnd, чтоб слушать сообщения. В нем есть карта сообщений (приписал в реализации):
G>>...

G>> У кого есть идеи — помогите, пожалуйста, советом: что-я-делаю-не-так??


O>Переусложняете.


O>GUI-поток и рабочий поток нужно держать в изоляции друг от друга, а здесь

O>рабочий поток построен на оконной процедуре, а еще связан с определениями из MFC.
O>Плохо это, так как код рабочего потока получится как минимум непереносимым, и
O>как только будет меняться GUI-часть, это повлечет за собой необходимость
O>изменений и в нем тоже.

O>Это во-первых. Во-вторых, вместо очереди оконных сообщений лучше взять что-нибудь

O>вроде std::queue, и использовать ее как контейнер данных для обоих классов.
O>Когда главное окно передает сообщение первому классу — оно просто создает объект message и
O>добавляет его в конец первой очереди. Выборка сообщений потоком может быть организована
O>по-разному, в зависимости от специфики задачи. Когда один из классов потока нуждается в
O>передаче сообщения главному окну, он просто ставит message в свою очередь и сигнализирует
O>главному окну каким-нибудь приватным оконным сообщением через PostMessage. Вот и вся механика.
O>Код получится в разы прозрачнее и гибче. Очереди, само собой, должны быть потокобезопасными,
O>то есть, EnterCriticalSection на входе и LeaveCriticalSection на выходе.

O>И уберите эти "ON_KR_RECALC", "KR_Object" и "const int dt=700;" — глаза режет.


Стиль ещё не успел почистить, но да — на мемент прочтения как-то так оно и получаться начало. А именно:


struct TEvent
{
    int source_id, dest_id;
    DWORD time_stamp, time_raise;
    string label;
};

// Всяческие типы данных и прочее используемое

class KR_Object
{ //такой именно, потому что я от него наследуюсь
protected:
    int ID;
    CContext *context;
    void send_event(int dest, UINT span=45);
public:
    virtual void do_job()=0;
    virtual void wakeup();
    void receive_event(TEvent msg);  // там внутри в реализации новая отсылка сообщения себе же
    void SetContext(CContext *cnt);
    virtual SomeInfo GetData() const=0;
};

typedef map<int,KR_Object*, less<int>> map_kr;
typedef list<TEvent*> lst_ev;
typedef vector<SomeInfo> TotalData;


А сама логика:

class CContext
{
private:
    map_kr objects;
    lst_ev event_pool;
    int id_counter;
    bool running;
    CRITICAL_SECTION locker; //а вот CCriticalSection почему-то глючил и не хотел объявляться((
public:
    CContext(void);
    void AddObject(KR_Object *NewObj);
    void RemoveByID(int del_id);
    void RemoveLast();
    int GetValidID() { return id_counter; }
    void SetEvent(TEvent *evnt);
        //бла-бла
    void Start();
    void Stop() { running=false; }
    ~CContext(void);
};

//--------------Это уже в cpp-реализации----------------

void CContext::Start() //стартую это в рабочем потоке 
{
    running=true;
    time_t now, raise;
    while(running)    // Пока переключение флага извне глючит, синхронизация нужна чтоли
    {
        Sleep(50); //Иначе рабочий поток помрет и не будет отвечать
        if (event_pool.empty())    continue;

        ::EnterCriticalSection(&locker);  //Синхронизация
        now=::GetTickCount();
        while(event_pool.front()->time_raise<=now)  //Сообщения по времени приходят, что там ниже не так важно
        {
            map_kr::iterator who=objects.find(event_pool.front()->dest_id);
            if (who!=objects.end())    who->second->receive_event(*event_pool.front());
            event_pool.pop_front();
            if (event_pool.empty())    break;
        }
        ::LeaveCriticalSection(&locker); //Синхронизация
    }
}

void CContext::AddObject(KR_Object *NewObj)
{
    NewObj->SetContext(this);
    ::EnterCriticalSection(&locker); 
    objects.insert(map_kr::value_type(id_counter,NewObj));
    id_counter++;
    ::LeaveCriticalSection(&locker);
    if (id_counter>INT32_MAX) throw exception("Too many objects");
    NewObj->wakeup();
}

void CContext::SetEvent(TEvent *evnt)
{  //добавляет новое сообщение объекту

    if (event_pool.empty() )
    {
        event_pool.push_back(evnt);
        return;
    }
    bool gotcha=false;
    for(lst_ev::const_iterator i=event_pool.begin(); i!=event_pool.end(); ++i)  
          // нужно чтобы была сортировка по времени прихода, потому тут нечто странное
    {
        if ((*i)->time_raise>evnt->time_raise)
        {
                event_pool.insert(i,evnt);
                gotcha=true;
                break;
        }
    }
    if (!gotcha) event_pool.push_back(evnt);
}


Сырой код в реализациях не так важен, суть в общей задумке — она вот такая

UINT WorkThreadProc( LPVOID pParam )
{
    CContext *work_context=(CContext *)pParam;
    work_context->Start();  //теперь проблем нет
    AfxEndThread(0,true);
    return 0;
}


Пока есть глюки, кривой код и т.д., которые можно и нужно почистить, но идея такая, до этого я по ошибке хотел сделать через оконные механизмы — нет, так и пашет лучше, и смысла больше.
Re[3]: MFC. Сообщения. Взаимодействие классов в потоке.
От: okman Беларусь https://searchinform.ru/
Дата: 08.03.12 13:22
Оценка: 1 (1)
Здравствуйте, Genco, Вы писали:

G>
G>//--------------Это уже в cpp-реализации----------------

G>void CContext::Start() //стартую это в рабочем потоке 
G>{
G>    running=true;
G>    time_t now, raise;
G>    while(running)    // Пока переключение флага извне глючит, синхронизация нужна чтоли
G>    {
G>        Sleep(50); //Иначе рабочий поток помрет и не будет отвечать
G>        if (event_pool.empty())    continue;
G>
G>...
G>


G>Пока есть глюки, кривой код и т.д., которые можно и нужно почистить, но идея такая, до этого я по ошибке хотел сделать через оконные механизмы — нет, так и пашет лучше, и смысла больше.


Я бы еще посоветовал избавиться от цикла, в котором крутится поток (while(running) и Sleep(50)).
Поток можно просто "уложить спать" — то есть, вызвать WaitForSingleEvent на неком событии.
Когда кто-нибудь добавляет сообщение в очередь, он будет дергать SetEvent — поток проснется,
заберет сообщение, обработает, и снова погрузится в спячку (если очередь пуста).
А крутить его в цикле — это значит задаром раздавать бесценные вычислительные ресурсы процессора.
В общем, разбирайтесь, это все есть на форумах, в инете, в книгах и т.п.
InitializeCriticalSection вызвать не забыли, надеюсь ?

Да, еще общие переменные, с которыми работает более одного потока одновременно (в данном
примере running, насколько я понимаю) лучше помечать ключевым словом volatile, иначе при
изменении переменной одним потоком ее значение может где-нибудь закэшироваться, и другие
потоки изменений не увидят.

P.S.
Тут на форуме принято избегать излишнего цитирования (оверквотинг).
Если отвечаете кому-либо, выделяйте только те цитаты, которые имеют непосредственное
отношение к сообщению.
Re[7]: MFC. Сообщения. Взаимодействие классов в потоке.
От: MasterZiv СССР  
Дата: 09.03.12 09:32
Оценка:
> Ключевой момент — это то, что слово "сообщения" я понял буквально (сказано —
> сделано), потому долго пытался прикрутить к классу-диспетчеру навеску с
> виндовыми обработчиками, в рабочем потоке они тормозили. Мне постучали по репе и
> сказали сделать по-людски (ниже как раз описана идея).

Никакого кода я что-то не нашёл, ну ладно.

Т.е. ты отказался от идеи использовать для этого оконные сообщения Windows
(message), так ? Если да, то ты на верном пути.
Если нет -- отказывайся.
Posted via RSDN NNTP Server 2.1 beta
Re[4]: MFC. Сообщения. Взаимодействие классов в потоке.
От: Genco  
Дата: 09.03.12 11:51
Оценка:
O>InitializeCriticalSection вызвать не забыли, надеюсь ?
Угу, просто не стал засорять форум полным кодом.

O>Я бы еще посоветовал избавиться от цикла, в котором крутится поток (while(running) и Sleep(50)).

O>Поток можно просто "уложить спать" — то есть, вызвать WaitForSingleEvent на неком событии.

O>Да, еще общие переменные, с которыми работает более одного потока одновременно (в данном

O>примере running, насколько я понимаю) лучше помечать ключевым словом volatile

О, теперь вообще приятно бегает, надежнее. Спасибо огромное!
Re[8]: MFC. Сообщения. Взаимодействие классов в потоке.
От: Genco  
Дата: 09.03.12 11:56
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>Т.е. ты отказался от идеи использовать для этого оконные сообщения Windows

MZ>(message), так ? Если да, то ты на верном пути.
MZ>Если нет -- отказывайся.

В точку и стало явно лучше.

MZ>Никакого кода я что-то не нашёл, ну ладно.

Оо Кусочки кода с сообщениями в первом посте; фрагменты с исправленями — в простыне чуть выше по топику.

/*Ушел работать напильником*/
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.