Обновление видов документа из потока
От: GraphX  
Дата: 29.07.03 12:26
Оценка:
Здравствуйте.

Возникла для меня немного тупиковая ситуация.
По ходу работы приложения Doc/View объект класса CDocument создает поток. В потоке цикл крутится в бесконечном режиме. По определенному событию таймера происходит запрос данных извне. После обновления списка, необходимо обновить все виды из потока. Обычно это делается при помощи метода UpdateAllViews(NULL), но в данном контексте происходит ошибка приложения Assertion Failed. Итак вопрос, как это обойти (сообщения какието послать или еще что).
Re: Обновление видов документа из потока
От: algol Россия about:blank
Дата: 29.07.03 12:48
Оценка:
Здравствуйте, GraphX, Вы писали:

GX>Возникла для меня немного тупиковая ситуация.

GX>По ходу работы приложения Doc/View объект класса CDocument создает поток. В потоке цикл крутится в бесконечном режиме. По определенному событию таймера происходит запрос данных извне. После обновления списка, необходимо обновить все виды из потока. Обычно это делается при помощи метода UpdateAllViews(NULL), но в данном контексте происходит ошибка приложения Assertion Failed. Итак вопрос, как это обойти (сообщения какието послать или еще что).

А зачем нужен отдельный поток, если данные все равно опрашиваются по таймеру?
Re: Обновление видов документа из потока
От: KGP http://kornilow.newmail.ru
Дата: 29.07.03 12:51
Оценка:
Здравствуйте, GraphX, Вы писали:

GX>Здравствуйте.


GX>Возникла для меня немного тупиковая ситуация.

GX>По ходу работы приложения Doc/View объект класса CDocument создает поток. В потоке цикл крутится в бесконечном режиме. По определенному событию таймера происходит запрос данных извне. После обновления списка, необходимо обновить все виды из потока. Обычно это делается при помощи метода UpdateAllViews(NULL), но в данном контексте происходит ошибка приложения Assertion Failed. Итак вопрос, как это обойти (сообщения какието послать или еще что).

когда ошибка и почему ?
может потоку указатель отдал не тот/так на CDocument
Re[2]: Обновление видов документа из потока
От: GraphX  
Дата: 29.07.03 12:52
Оценка:
Здравствуйте, algol, Вы писали:

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


GX>>Возникла для меня немного тупиковая ситуация.

GX>>По ходу работы приложения Doc/View объект класса CDocument создает поток. В потоке цикл крутится в бесконечном режиме. По определенному событию таймера происходит запрос данных извне. После обновления списка, необходимо обновить все виды из потока. Обычно это делается при помощи метода UpdateAllViews(NULL), но в данном контексте происходит ошибка приложения Assertion Failed. Итак вопрос, как это обойти (сообщения какието послать или еще что).

A>А зачем нужен отдельный поток, если данные все равно опрашиваются по таймеру?


Дело в том, что еще не определен период, в котором будут опрашиваться данные, а также их количество. да и потом при добавлении новой записи к примеру процедура опроса будет к сожалению заблокирована!
Re[2]: Обновление видов документа из потока
От: GraphX  
Дата: 29.07.03 12:56
Оценка:
Здравствуйте, KGP, Вы писали:

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


GX>>Здравствуйте.


GX>>Возникла для меня немного тупиковая ситуация.

GX>>По ходу работы приложения Doc/View объект класса CDocument создает поток. В потоке цикл крутится в бесконечном режиме. По определенному событию таймера происходит запрос данных извне. После обновления списка, необходимо обновить все виды из потока. Обычно это делается при помощи метода UpdateAllViews(NULL), но в данном контексте происходит ошибка приложения Assertion Failed. Итак вопрос, как это обойти (сообщения какието послать или еще что).

KGP>когда ошибка и почему ?

Ошибка при вызове pDoc->UpdateAllViews(NULL) из потока
pDoc получается путем передачи через параметр LPVOID* функции рабочего потока.
KGP>может потоку указатель отдал не тот/так на CDocument
Но до этого я пользуюсь в других целях этим указателем нормально. (Там в документе мой объектик-список живет, я с ним и работаю)
Re[3]: Обновление видов документа из потока
От: Sasparella США  
Дата: 29.07.03 15:19
Оценка:
из потока посылайье главному окну сообщение, в ответ на которое обновляйте.

НО, посылайте не

pMainWnd->SendMessage(...)

а так

::SendMessage(pMainWnd->GetSafeHwnd(),...)
Re[4]: Обновление видов документа из потока
От: Serguei666 Беларусь  
Дата: 29.07.03 15:49
Оценка:
Здравствуйте, Sasparella, Вы писали:

S>из потока посылайье главному окну сообщение, в ответ на которое обновляйте.


S>НО, посылайте не


S>
S>pMainWnd->SendMessage(...)
S>

S>а так

S>
S>::SendMessage(pMainWnd->GetSafeHwnd(),...)
S>

А какая разница? Посмотрите на код CWnd::SendMessage(), он делает то же, что вы и предлагаете, т.е. берет указатель this, из него извлекает m_hWnd и передает m_hWnd первым параметром глобальной функции ::SendMessage

_AFXWIN_INLINE LRESULT CWnd::SendMessage(UINT message, WPARAM wParam, LPARAM lParam)
    { ASSERT(::IsWindow(m_hWnd)); return ::SendMessage(m_hWnd, message, wParam, lParam); }
Хотите сказать 'спасибо'? Тогда поставьте оценку
Re[5]: Обновление видов документа из потока
От: Kiper Израиль  
Дата: 29.07.03 19:33
Оценка:
Разница в том, что из потока нельзя напрямую доставать окна. Вы можете прямо обращаться из потока только к окну, которое его породило. А по другому, через главное род. окно, и желательно без пойнтеров (т.е. использовать HWND) и желательно PostMessage()
Жизненный опыт похож на выигрышную лотерею, купленную после тиража.
Re[6]: Обновление видов документа из потока
От: GraphX  
Дата: 30.07.03 07:25
Оценка:
Здравствуйте, Kiper, Вы писали:

K>Разница в том, что из потока нельзя напрямую доставать окна. Вы можете прямо обращаться из потока только к окну, которое его породило. А по другому, через главное род. окно, и желательно без пойнтеров (т.е. использовать HWND) и желательно PostMessage()


Хмм. А как же я могу послать сообщение классу CDocument когда в нем нету SendMessage, он не является наследником CWnd.
В ходе своих ночных размышлений пришел к нескольким вариантам:
1. Можно привязаться к таймеру, по которому идет запрос данных (Таймер системный НО, создается он именно в потоке, поэтому как то его надо обратно передать) и обновлять окна по этому таймеру. Вопрос, можно ли както "найти" хэндл таймера?

2. Достать каждый CView через хэндлы и в цикле создавая MFCшные объекты при помощи FromHandle обновлять все окна (но это у меня вчера не захотело работать — окна не обновлялись).
К примеру (у меня окна обновляться не хотели):
   POSITION pos = GetFirstViewPosition();
   CWnd *pWnd;
   while (pos != NULL)
   {
      CView* pView = GetNextView(pos);
      pWnd = CWnd::FromHandle(pView->m_hWnd);
      pWnd->UpdateWindow();
   }



3. Написать какимлибо образом диспатчер своего сообщения в CDocument — ловить свое сообщение и выполнять действие. Тут тоже пока я не врубаюсь как послать потом это сообщение чтобы оно дошло до CDocument'а

Вобщем по всем 3м пунктам у меня нифига не вышло.
Re[7]: Обновление видов документа из потока
От: algol Россия about:blank
Дата: 30.07.03 07:48
Оценка:
Здравствуйте, GraphX, Вы писали:

GX>Хмм. А как же я могу послать сообщение классу CDocument когда в нем нету SendMessage, он не является наследником CWnd.


Зато его можно послать например в CMainFrame (используя переданный в поток hWnd), который и передаст его в CDocument.

GX>2. Достать каждый CView через хэндлы и в цикле создавая MFCшные объекты при помощи FromHandle обновлять все окна (но это у меня вчера не захотело работать — окна не обновлялись).

GX>К примеру (у меня окна обновляться не хотели):
GX>
GX>   POSITION pos = GetFirstViewPosition();
GX>   CWnd *pWnd;
GX>   while (pos != NULL)
GX>   {
GX>      CView* pView = GetNextView(pos);
GX>      pWnd = CWnd::FromHandle(pView->m_hWnd);
      pWnd->>UpdateWindow();
GX>   }   
GX>


Вот про это и говорили, что ссылки на оконные классы действительны только в потоке, создавшем окно. Чтобы этот вариант работал, нужно собрать все hWnd видов и передать их потоку при инициализации. hWnd нужно получать в том потоке, который создал окно. А уже в другом потоке использовать FromHandle.
Re[8]: Обновление видов документа из потока
От: GraphX  
Дата: 30.07.03 08:14
Оценка:
Здравствуйте, algol, Вы писали:

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


GX>>Хмм. А как же я могу послать сообщение классу CDocument когда в нем нету SendMessage, он не является наследником CWnd.


A>Зато его можно послать например в CMainFrame (используя переданный в поток hWnd), который и передаст его в CDocument.


Ага.. сейчас попробую этот вариант! Тем более я немного по другому делал. Я доставал m_hWnd через AfxGetApp... в рабочем потоке. Полагаю это меня и подводило.

GX>>2. Достать каждый CView через хэндлы и в цикле создавая MFCшные объекты при помощи FromHandle обновлять все окна (но это у меня вчера не захотело работать — окна не обновлялись).

GX>>К примеру (у меня окна обновляться не хотели):
GX>>
GX>>   POSITION pos = GetFirstViewPosition();
GX>>   CWnd *pWnd;
GX>>   while (pos != NULL)
GX>>   {
GX>>      CView* pView = GetNextView(pos);
GX>>      pWnd = CWnd::FromHandle(pView->m_hWnd);
      pWnd->>>UpdateWindow();
GX>>   }   
GX>>


A>Вот про это и говорили, что ссылки на оконные классы действительны только в потоке, создавшем окно. Чтобы этот вариант работал, нужно собрать все hWnd видов и передать их потоку при инициализации. hWnd нужно получать в том потоке, который создал окно. А уже в другом потоке использовать FromHandle.


В этом случае при добавлении нового вида, он не будет обновляться, а при удалении — возникнет ошибка. Тогда уж надо както доставать хэндлы видов динамически из рабочего потока. А например если создать список хэндлов в главном потоке.. а в рабочем поиметь доступ к этому списку. Список — это не оконный же класс.
Re[8]: Обновление видов документа из потока
От: GraphX  
Дата: 30.07.03 13:30
Оценка:
Здравствуйте, algol, Вы писали:

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


GX>>Хмм. А как же я могу послать сообщение классу CDocument когда в нем нету SendMessage, он не является наследником CWnd.


A>Зато его можно послать например в CMainFrame (используя переданный в поток hWnd), который и передаст его в CDocument.


Посылаю сообщение, но до этого окна оно не доходит
Делаю так:

Создаю поток
    CWnd *pWnd = AfxGetMainWnd();
    LPVOID *pParams = new LPVOID[2];
    pParams[0] = (LPVOID)this;
    pParams[1] = (LPVOID)pWnd->GetSafeHwnd();

    m_pthrMainTic = AfxBeginThread((AFX_THREADPROC)TicThread, (LPVOID)pParams);
    m_pthrMainTic->SuspendThread();
    m_pthrMainTic->m_bAutoDelete=FALSE;
    m_pthrMainTic->ResumeThread();

В потоке делаю так

UINT TicThread(LPVOID pParam)
{
    LPVOID *pParams = (LPVOID *)pParam;
    CGuardManDoc *pDoc = (CGuardManDoc *)pParams[0];
    if (pDoc == NULL || !pDoc->IsKindOf(RUNTIME_CLASS(CGuardManDoc))) return 1;
    HWND hMainWnd = (HWND)pParams[1];
......

И под конец посылаю мессэдж в этом потоке

......
    ::SendMessage(hMainWnd, WM_USER_UPDATEVIEWS, NULL, NULL);
......
}


Потом уже в MainFrame'е

BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
    // TODO: Add your specialized code here and/or call the base class
    if (nID == WM_USER_UPDATEVIEWS) 
    {
        // Здесь ловлю сообщение
    }
    return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}


Где я напортачил?
Re[9]: Обновление видов документа из потока
От: algol Россия about:blank
Дата: 30.07.03 13:59
Оценка:
Здравствуйте, GraphX, Вы писали:


GX>Посылаю сообщение, но до этого окна оно не доходит

GX>Делаю так:

GX>Создаю поток

GX>
GX>    CWnd *pWnd = AfxGetMainWnd();
GX>    LPVOID *pParams = new LPVOID[2];
GX>    pParams[0] = (LPVOID)this;
GX>    pParams[1] = (LPVOID)pWnd->GetSafeHwnd();

GX>    m_pthrMainTic = AfxBeginThread((AFX_THREADPROC)TicThread, (LPVOID)pParams);
GX>    m_pthrMainTic->SuspendThread();
GX>    m_pthrMainTic->m_bAutoDelete=FALSE;
GX>    m_pthrMainTic->ResumeThread();
GX>

GX>В потоке делаю так

GX>
GX>UINT TicThread(LPVOID pParam)
GX>{
GX>    LPVOID *pParams = (LPVOID *)pParam;
GX>    CGuardManDoc *pDoc = (CGuardManDoc *)pParams[0];
GX>    if (pDoc == NULL || !pDoc->IsKindOf(RUNTIME_CLASS(CGuardManDoc))) return 1;
GX>    HWND hMainWnd = (HWND)pParams[1];
GX>......
GX>

GX>И под конец посылаю мессэдж в этом потоке

GX>
GX>......
GX>    ::SendMessage(hMainWnd, WM_USER_UPDATEVIEWS, NULL, NULL);
GX>......
GX>}
GX>


GX>Потом уже в MainFrame'е


GX>
GX>BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
GX>{
GX>    // TODO: Add your specialized code here and/or call the base class
GX>    if (nID == WM_USER_UPDATEVIEWS) 
GX>    {
GX>        // Здесь ловлю сообщение
GX>    }
GX>    return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
GX>}
GX>


GX>Где я напортачил?


OnCmdMsg ловит только WM_COMMAND. Нужно просто вставить ON_MESSAGE в карту сообщений. А вместо SendMessage лучше использовать PostMessage.
Re[6]: Обновление видов документа из потока
От: Serguei666 Беларусь  
Дата: 30.07.03 15:30
Оценка:
Здравствуйте, Kiper, Вы писали:

K>Разница в том, что из потока нельзя напрямую доставать окна.

И что же эта фраза конкретно означает? В частности, на какую функцию ссылается фраза "напрямую доставать окна"


K>Вы можете прямо обращаться из потока только к окну, которое его породило.

Это предложение мне тоже непонятно. Что оно означает? Какие конкретно действия мне нельзя делать?

K>А по другому, через главное род. окно, и желательно без пойнтеров (т.е. использовать HWND) и желательно PostMessage()

Почему? Не вижу никаких проблем. pMainWnd->SendMessage(...) будет работать, даже если pMainWnd было создано в другой цепочке.

Я, кстати, написал, что не вижу разницы между
pMainWnd->SendMessage(...)
и
::SendMessage(pMainWnd->GetSafeHwnd(),...)

И разницы действительно нет — я и код привел для иллюстрации. Хотите попробовать доказать обратное?
Хотите сказать 'спасибо'? Тогда поставьте оценку
Re[7]: Обновление видов документа из потока
От: Serguei666 Беларусь  
Дата: 30.07.03 15:38
Оценка:
Здравствуйте, GraphX, Вы писали:

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


K>>Разница в том, что из потока нельзя напрямую доставать окна. Вы можете прямо обращаться из потока только к окну, которое его породило. А по другому, через главное род. окно, и желательно без пойнтеров (т.е. использовать HWND) и желательно PostMessage()


GX>Хмм. А как же я могу послать сообщение классу CDocument когда в нем нету SendMessage, он не является наследником CWnd.

Вы правы. Документу послать сообщение вы не можете — потому что посылать сообщения можно только окнам. Что вы могли бы сделать — послать сообщение окну, которое переадресовало бы его документу. Какому окну? Да тому же MainFrame, например. Стандартно MainFrame переадресует ваши WM_COMMAND сообщения документу.

GX>В ходе своих ночных размышлений пришел к нескольким вариантам:

GX>1. Можно привязаться к таймеру, по которому идет запрос данных (Таймер системный НО, создается он именно в потоке, поэтому как то его надо обратно передать) и обновлять окна по этому таймеру. Вопрос, можно ли както "найти" хэндл таймера?
Обновлять окна по таймеру — это то, что нужно. Зачем вам хэндл таймера, кстати? Нетуи у таймера никакого хэндла. Есть ID.

GX>2. Достать каждый CView через хэндлы и в цикле создавая MFCшные объекты при помощи FromHandle обновлять все окна (но это у меня вчера не захотело работать — окна не обновлялись).

Как бы я делал:
из цепочки, где таймер, по событию таймера посылал команду документу обновится. По этой команде документ вызывает UpdateAllViews

GX>К примеру (у меня окна обновляться не хотели):

GX>
GX>   POSITION pos = GetFirstViewPosition();
GX>   CWnd *pWnd;
GX>   while (pos != NULL)
GX>   {
GX>      CView* pView = GetNextView(pos);
GX>      pWnd = CWnd::FromHandle(pView->m_hWnd);
      pWnd->>UpdateWindow();
GX>   }   
GX>

Этот код я бы посоветовал вам убрать. Он бесполезен по двум причинам:
1. По моему, это же самое делает UpdateAllViews
2. Строчки
pWnd = CWnd::FromHandle(pView->m_hWnd);
pWnd->UpdateWindow();
бессмысленны


GX>3. Написать какимлибо образом диспатчер своего сообщения в CDocument — ловить свое сообщение и выполнять действие. Тут тоже пока я не врубаюсь как послать потом это сообщение чтобы оно дошло до CDocument'а


GX>Вобщем по всем 3м пунктам у меня нифига не вышло.
Хотите сказать 'спасибо'? Тогда поставьте оценку
Re[8]: Обновление видов документа из потока
От: GraphX  
Дата: 30.07.03 17:31
Оценка:
Здравствуйте, Serguei666, Вы писали:

K>>>Разница в том, что из потока нельзя напрямую доставать окна. Вы можете прямо обращаться из потока только к окну, которое его породило. А по другому, через главное род. окно, и желательно без пойнтеров (т.е. использовать HWND) и желательно PostMessage()


GX>>Хмм. А как же я могу послать сообщение классу CDocument когда в нем нету SendMessage, он не является наследником CWnd.

S>Вы правы. Документу послать сообщение вы не можете — потому что посылать сообщения можно только окнам. Что вы могли бы сделать — послать сообщение окну, которое переадресовало бы его документу. Какому окну? Да тому же MainFrame, например. Стандартно MainFrame переадресует ваши WM_COMMAND сообщения документу.

Теперь я как раз и делаю по этому варианту. Правда вляпался что когда создается Документ объекта главного окна еще нет. Точнее не получается воспользоваться AfxGetMainWnd(). А тогда когда же мне запускать поток, передавай туда хэндл главного окна получить которое я не могу

GX>>В ходе своих ночных размышлений пришел к нескольким вариантам:

GX>>1. Можно привязаться к таймеру, по которому идет запрос данных (Таймер системный НО, создается он именно в потоке, поэтому как то его надо обратно передать) и обновлять окна по этому таймеру. Вопрос, можно ли както "найти" хэндл таймера?
S>Обновлять окна по таймеру — это то, что нужно. Зачем вам хэндл таймера, кстати? Нетуи у таймера никакого хэндла. Есть ID.
Аз есьм! Как же без хэндла. Просто я создаю таймер уже в рабочем потоке при помощи апишных функций, а это значит, что он заносится в списки Виндов под какимто именем, оказывается по этому имени можно получить хэндл на таймер. Только вот опять-же это не удобно так как получать его надо уже после того как таймер создастся.. а отловить этот момент тяжко хотя можно при помощи событий.. хмм а эта мысля мне еще не приходила!

GX>>2. Достать каждый CView через хэндлы и в цикле создавая MFCшные объекты при помощи FromHandle обновлять все окна (но это у меня вчера не захотело работать — окна не обновлялись).

S>Как бы я делал:
S>из цепочки, где таймер, по событию таймера посылал команду документу обновится. По этой команде документ вызывает UpdateAllViews
Да, это конечно хорошо, а если окна не надо обновлять, то мы их все равно обновляем
GX>>К примеру (у меня окна обновляться не хотели):
GX>>
GX>>   POSITION pos = GetFirstViewPosition();
GX>>   CWnd *pWnd;
GX>>   while (pos != NULL)
GX>>   {
GX>>      CView* pView = GetNextView(pos);
GX>>      pWnd = CWnd::FromHandle(pView->m_hWnd);
      pWnd->>>UpdateWindow();
GX>>   }   
GX>>

S>Этот код я бы посоветовал вам убрать. Он бесполезен по двум причинам:
S>1. По моему, это же самое делает UpdateAllViews
S>2. Строчки
S>pWnd = CWnd::FromHandle(pView->m_hWnd);
pWnd->>UpdateWindow();
S>бессмысленны
Это не бессмысленно когда такой код запускается из другого потока
Так как UpdateAllViews выдает ошибку!

GX>>3. Написать какимлибо образом диспатчер своего сообщения в CDocument — ловить свое сообщение и выполнять действие. Тут тоже пока я не врубаюсь как послать потом это сообщение чтобы оно дошло до CDocument'а


GX>>Вобщем по всем 3м пунктам у меня нифига не вышло.
Re[9]: Обновление видов документа из потока
От: Serguei666 Беларусь  
Дата: 30.07.03 18:41
Оценка:
Здравствуйте, GraphX, Вы писали:

GX>Теперь я как раз и делаю по этому варианту. Правда вляпался что когда создается Документ объекта главного окна еще нет. Точнее не получается воспользоваться AfxGetMainWnd(). А тогда когда же мне запускать поток, передавай туда хэндл главного окна получить которое я не могу


Смотрим на стандартно сгенерированную Визардом функцию InitInstance

...
// Тут создается главное окно
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
return FALSE;
m_pMainWnd = pMainFrame;

// Тут создается первый документ
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
...

Как видите, в стандартном случае главное окно создается до создания первого документа. У вас наоборот. Почему? Если вы это сделали специально, хотелось бы знать, с какой целью. Если случайно, то верните все как было и у вас все будет работать.

GX>Аз есьм! Как же без хэндла. Просто я создаю таймер уже в рабочем потоке при помощи апишных функций, а это значит, что он заносится в списки Виндов под какимто именем, оказывается по этому имени можно получить хэндл на таймер. Только вот опять-же это не удобно так как получать его надо уже после того как таймер создастся.. а отловить этот момент тяжко хотя можно при помощи событий.. хмм а эта мысля мне еще не приходила!


Звучит ваше объяснение устрашающе.
SetTimer возвращает ID таймера. Зачем вам к ID еще и хэндл?

GX>Да, это конечно хорошо, а если окна не надо обновлять, то мы их все равно обновляем

Не понял. Разве не обновление окон было вашим вопросом? Вы же написали "После обновления списка, необходимо обновить все виды из потока". Или я чего-то недоглядел?

GX>>>К примеру (у меня окна обновляться не хотели):

GX>>>
GX>>>   POSITION pos = GetFirstViewPosition();
GX>>>   CWnd *pWnd;
GX>>>   while (pos != NULL)
GX>>>   {
GX>>>      CView* pView = GetNextView(pos);
GX>>>      pWnd = CWnd::FromHandle(pView->m_hWnd);
      pWnd->>>>UpdateWindow();
GX>>>   }   
GX>>>

S>>Этот код я бы посоветовал вам убрать. Он бесполезен по двум причинам:
S>>1. По моему, это же самое делает UpdateAllViews
S>>2. Строчки
S>>pWnd = CWnd::FromHandle(pView->m_hWnd);
pWnd->>>UpdateWindow();
S>>бессмысленны
GX>Это не бессмысленно когда такой код запускается из другого потока
GX>Так как UpdateAllViews выдает ошибку!
Я же вам написал, как эту ошибку преодолеть — вы не вызываете из другого потока функцию документа UpdateAllViews — а посылаете сообщение главному окну, и документ, реагируя на сообщение, делает UpdateAllViews

GX>>>3. Написать какимлибо образом диспатчер своего сообщения в CDocument — ловить свое сообщение и выполнять действие. Тут тоже пока я не врубаюсь как послать потом это сообщение чтобы оно дошло до CDocument'а

Этого я вам не советовал.
И вообще, я сторонник простых решений.

GX>>>Вобщем по всем 3м пунктам у меня нифига не вышло.

Именно для этого му на форуме и торчим — помогать другим решать проблемы. Что у вас не вышло?
Хотите сказать 'спасибо'? Тогда поставьте оценку
Re[10]: Обновление видов документа из потока
От: GraphX  
Дата: 30.07.03 19:37
Оценка:
Здравствуйте, Serguei666, Вы писали:

GX>>Теперь я как раз и делаю по этому варианту. Правда вляпался что когда создается Документ объекта главного окна еще нет. Точнее не получается воспользоваться AfxGetMainWnd(). А тогда когда же мне запускать поток, передавай туда хэндл главного окна получить которое я не могу


S>Смотрим на стандартно сгенерированную Визардом функцию InitInstance


S>...

S>// Тут создается главное окно
S>CMainFrame* pMainFrame = new CMainFrame;
S>if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
S> return FALSE;
S>m_pMainWnd = pMainFrame;

S>// Тут создается первый документ

S>CCommandLineInfo cmdInfo;
S>ParseCommandLine(cmdInfo);
S>...

S>Как видите, в стандартном случае главное окно создается до создания первого документа. У вас наоборот. Почему? Если вы это сделали специально, хотелось бы знать, с какой целью. Если случайно, то верните все как было и у вас все будет работать.


У меня стоит .NET.. Там генерится такой код

    CSingleDocTemplate* pDocTemplate;
    pDocTemplate = new CSingleDocTemplate(
        IDR_MAINFRAME,
        RUNTIME_CLASS(CGuardManDoc),
        RUNTIME_CLASS(CMainFrame),       // main SDI frame window
        RUNTIME_CLASS(CGuardManView));
    AddDocTemplate(pDocTemplate);
    // Parse command line for standard shell commands, DDE, file open
    CCommandLineInfo cmdInfo;
    ParseCommandLine(cmdInfo);

Воткнул старт нового потока после этой строки, и все встало на свои места.. и обновление тож работает Спасибо всем!
Сделал через обычное сообщение для Main Frame'а.

GX>>Аз есьм! Как же без хэндла. Просто я создаю таймер уже в рабочем потоке при помощи апишных функций, а это значит, что он заносится в списки Виндов под какимто именем, оказывается по этому имени можно получить хэндл на таймер. Только вот опять-же это не удобно так как получать его надо уже после того как таймер создастся.. а отловить этот момент тяжко хотя можно при помощи событий.. хмм а эта мысля мне еще не приходила!


S>Звучит ваше объяснение устрашающе.

S>SetTimer возвращает ID таймера. Зачем вам к ID еще и хэндл?
Я пользовался hTimer = CreateWaitableTimer(NULL, FALSE, _T("Lala"));
Работает тоже неплохо.

GX>>Да, это конечно хорошо, а если окна не надо обновлять, то мы их все равно обновляем

S>Не понял. Разве не обновление окон было вашим вопросом? Вы же написали "После обновления списка, необходимо обновить все виды из потока". Или я чего-то недоглядел?

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

GX>>>>К примеру (у меня окна обновляться не хотели):

GX>>>>
GX>>>>   POSITION pos = GetFirstViewPosition();
GX>>>>   CWnd *pWnd;
GX>>>>   while (pos != NULL)
GX>>>>   {
GX>>>>      CView* pView = GetNextView(pos);
GX>>>>      pWnd = CWnd::FromHandle(pView->m_hWnd);
      pWnd->>>>>UpdateWindow();
GX>>>>   }   
GX>>>>

S>>>Этот код я бы посоветовал вам убрать. Он бесполезен по двум причинам:
S>>>1. По моему, это же самое делает UpdateAllViews
S>>>2. Строчки
S>>>pWnd = CWnd::FromHandle(pView->m_hWnd);
pWnd->>>>UpdateWindow();
S>>>бессмысленны
GX>>Это не бессмысленно когда такой код запускается из другого потока
GX>>Так как UpdateAllViews выдает ошибку!
S>Я же вам написал, как эту ошибку преодолеть — вы не вызываете из другого потока функцию документа UpdateAllViews — а посылаете сообщение главному окну, и документ, реагируя на сообщение, делает UpdateAllViews
Да да.. теперь оно живет именно так!

GX>>>>3. Написать какимлибо образом диспатчер своего сообщения в CDocument — ловить свое сообщение и выполнять действие. Тут тоже пока я не врубаюсь как послать потом это сообщение чтобы оно дошло до CDocument'а

S>Этого я вам не советовал.
S>И вообще, я сторонник простых решений.

Аналогично, просто не сразу их видишь именно из за простоты
GX>>>>Вобщем по всем 3м пунктам у меня нифига не вышло.
S>Именно для этого му на форуме и торчим — помогать другим решать проблемы. Что у вас не вышло?
Эта фраза была уже давно.
Re[7]: Обновление видов документа из потока
От: algol Россия about:blank
Дата: 31.07.03 05:52
Оценка:
Здравствуйте, Serguei666, Вы писали:

K>>Разница в том, что из потока нельзя напрямую доставать окна.

S>И что же эта фраза конкретно означает? В частности, на какую функцию ссылается фраза "напрямую доставать окна"
S>

K>>Вы можете прямо обращаться из потока только к окну, которое его породило.

S>Это предложение мне тоже непонятно. Что оно означает? Какие конкретно действия мне нельзя делать?

K>>А по другому, через главное род. окно, и желательно без пойнтеров (т.е. использовать HWND) и желательно PostMessage()

S>Почему? Не вижу никаких проблем. pMainWnd->SendMessage(...) будет работать, даже если pMainWnd было создано в другой цепочке.

В MSDN есть статьи "First Aid for the Thread-Impaired: Using Multiple Threads with MFC" (MSJ December 1996) и "More First Aid for the Thread Impaired: Cool Ways to Take Advantage of Multithreading" (MSJ July 1997). Оч-чень рекомендую ознакомиться. А здесь приведу маленькую цитату:

Don't expect to be able to access any MFC objects not created within your thread. Each thread gets its own handle map within MFC, which means, for instance, that a handle to a CWnd passed to a thread method may be invalid inside the thread. Instead, pass handles to threads as their native HANDLE type, and then use the FromHandle or Attach methods to obtain a handle to an MFC object. Sometimes you don't have to go to this much trouble. CThreadSafeWnd::PaintBall, for instance, takes a pointer to a CWnd as an argument and works fine. It would take delving deeply into Windows internals to determine which situations require special handling and which don't.

Re[8]: Обновление видов документа из потока
От: Serguei666 Беларусь  
Дата: 31.07.03 11:29
Оценка: 1 (1)
Здравствуйте, algol, Вы писали:

A>В MSDN есть статьи "First Aid for the Thread-Impaired: Using Multiple Threads with MFC" (MSJ December 1996) и "More First Aid for the Thread Impaired: Cool Ways to Take Advantage of Multithreading" (MSJ July 1997). Оч-чень рекомендую ознакомиться.


Спасибо, не буду, потому что не думаю, что я там найду что-то, чего я не знаю.


A>А здесь приведу маленькую цитату:

A>Don't expect to be able to access any MFC objects not created within your thread.

Именно. Речь об "any MFC objects". Т.е.в общем случае работать не будет, а в частных случаях — будет без проблем. Важно знать детали реализации, а без них сообщения типа того, что запостил Sasparella — бесполезны и бессмысленны.


A>Each thread gets its own handle map within MFC, which means, for instance, that a handle to a CWnd passed to a thread method may be invalid inside the thread.


Если речь идет о CWnd, то мы передаем не "handle", а "pointer"


A>Instead, pass handles to threads as their native HANDLE type, and then use the FromHandle or Attach methods to obtain a handle to an MFC object. Sometimes you don't have to go to this much trouble. CThreadSafeWnd::PaintBall, for instance, takes a pointer to a CWnd as an argument and works fine. It would take delving deeply into Windows internals to determine which situations require special handling and which don't.


Ага. Именно это я и говорю — в некоторых случаях все будет распрекрасно работать.
Хотите сказать 'спасибо'? Тогда поставьте оценку
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.