Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Вопрос по поводу потоков

318
04 сентября 2008 года
nof
193 / / 03.04.2006
Ребят, объясните пожалуйста:
1. чем отличаются _beginthreadex, AfxBeginThread и CreateThread? Ясное дело, что аргументами. Интересуют какие-то принципиальные отличия.
2. возможно ли в потоке, созданном какой-то из этих функций, обновлять данные (UpdateData()) в главном окне MFC-приложения?
3. возможно ли в MFC приложении запустить диалог в отдельном потоке? Если да, то как в двух словах.
288
04 сентября 2008 года
nikitozz
1.2K / / 09.03.2007
Цитата: nof
Ребят, объясните пожалуйста:
1. чем отличаются _beginthreadex, AfxBeginThread и CreateThread? Ясное дело, что аргументами. Интересуют какие-то принципиальные отличия.



_beginthreadex - функция из библиотеки С\С++. AfxBeginThread - аналог из MFC, CreateThread - функция из WinApi. По идее в Windows и _beginthreadex и AfxBeginThread в конечном счете обращаются к CreateThread. Но _beginthreadex в отличие от CreateThread выполняет предварительную инициализацию библиотеки С\С++. Так что при альтернативе CreateThread или _beginthreadex многие авторы советуют остановить свой выбор на _beginthreadex.

Цитата: nof
2. возможно ли в потоке, созданном какой-то из этих функций, обновлять данные (UpdateData()) в главном окне MFC-приложения?



Теоретически можно, но связано в рядом проблем.

Цитата: nof

3. возможно ли в MFC приложении запустить диалог в отдельном потоке? Если да, то как в двух словах.



Да. Но вероятнее всего придется использовать т.н. UI Thread. Т.е. потоки пользовательского интерфейса, а не просто рабочие.

14
04 сентября 2008 года
Phodopus
3.3K / / 19.06.2008
Вчера задавали подобный вопрос, вот хорошая статья
87
04 сентября 2008 года
Kogrom
2.7K / / 02.02.2008
Цитата: nikitozz
_beginthreadex - функция из библиотеки С\С++.


Уточнение. Если не ошибаюсь, в стандартных библиотеках С\С++ нет такой функции. Это изобретение Microsoft. Таким образом, она может отсутствовать в компиляторах от других разработчиков. Ну и независимости от ОС поэтому наверно нет...

318
04 сентября 2008 года
nof
193 / / 03.04.2006
Цитата: nikitozz

[QUOTE=nof]
2. возможно ли в потоке, созданном какой-то из этих функций, обновлять данные (UpdateData()) в главном окне MFC-приложения?


Теоретически можно, но связано в рядом проблем.[/QUOTE]
А подробнее? :)
Проблема заключается в том, что в моём приложении отдельный поток будет получать данные и должен их как-то отображать на форму. Но дело в том, что данные на форме обновлять некому..

318
04 сентября 2008 года
nof
193 / / 03.04.2006
Цитата: Kogrom
Уточнение. Если не ошибаюсь, в стандартных библиотеках С\С++ нет такой функции. Это изобретение Microsoft. Таким образом, она может отсутствовать в компиляторах от других разработчиков. Ну и независимости от ОС поэтому наверно нет...


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

добавлено:
ааа, только что идея появилась для обновления просто WM_TIMER использовать :D

4.8K
04 сентября 2008 года
fakel15
54 / / 02.12.2005
Мне кажется, что если по таймеру, то программа лишние телодвижения делать будет, когда они не нужны (например: данные не изменяются (т.е. их на форме по сути обновлять не надо), а по таймеру они будут периодически обновляться).
В данном случае можно использовать сообщения. Если данные изменились в рабочем потоке, то он просто отправляет диалогу сообщение с требованием обновить.
288
04 сентября 2008 года
nikitozz
1.2K / / 09.03.2007
Цитата: nof
А подробнее? :)
Проблема заключается в том, что в моём приложении отдельный поток будет получать данные и должен их как-то отображать на форму. Но дело в том, что данные на форме обновлять некому..



А поподробней проблема будет заключаться в том, что нельзя будет просто передать второму потоку скажем указатель на CWnd и использовать его для изменения данных. Причина в т.н. Handle map, которыми MFC пользуется для перевода из HWND в CWnd. Так вот эти таблицы уникальны для каждого потока. Не найдя подходящий HWND для переданного CWnd, MFC будет "ругаться". Самое обидное заключается в том, что даже не прибегая к этому нехорошему способу (передачи CWnd), а пытаясь решить это окольными путями вы скорее всего тоже получите кучу assert'ов.
Вообщем самый правильный путь - это не пытаться из потока, выбирающего данные, напрямую обращаться к окнам или элементам управления главного окна. Наверное более правильным будет использовать этот поток только как источник данных для первичного потока (предположим с помощью очередей или посылки оконных сообщений), а уже все обновление на форме возложить исключительно на первичный поток.

11
04 сентября 2008 года
oxotnik333
2.9K / / 03.08.2007
передавайте в параметры потока структуру, которая будет содержать в себе указатели на необходимые контролы и в потоке работайте с этими указателями.

типа того:
Код:
struct Params
{
  CEdit *edit;
  CWnd *wnd;
  .....
}Params;
....
//перед вызовом потока в классе главного окна:

Params *param = new Params;
param->edit = this->edit1;
param->wnd = this;

CreateThread (NULL, 0, MyThread, (LPVOID)param, NULL, NULL);


DWORT WINAPI MyThread (LPVOID pParam)
{
  Param *p = (Param*)pParam;
  while(....)
  {
    p->edit->SetWindowText("BlaBla");
    p->wnd->SetWindowText(SomText);
  }

}
ЗЫ: для любителей поговорить насчет синхронизации и удаления указателей: показал только принцип, думайте сами как удалять и синхронизировать :)
288
04 сентября 2008 года
nikitozz
1.2K / / 09.03.2007
Цитата: oxotnik333
передавайте в параметры потока структуру, которая будет содержать в себе указатели на необходимые контролы и в потоке работайте с этими указателями.



Ну вот. Опять мы с oxotnik333 не сошлись во мнении. :D
Использование такого способа в Debug версии - скорее всего будет выдавать кучу assert'ов. В release версии - возможно будет работать, а возможно и нет, все зависит от вызываемых функций.

11
04 сентября 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: nikitozz
Ну вот. Опять мы с oxotnik333 не сошлись во мнении. :D
Использование такого способа в Debug версии - скорее всего будет выдавать кучу assert'ов. В release версии - возможно будет работать, а возможно и нет, все зависит от вызываемых функций.


Вот веришь нет, сделал точно так же как и написал, все работает почему то...
Могу исходники выложить

288
04 сентября 2008 года
nikitozz
1.2K / / 09.03.2007
Цитата: oxotnik333
Вот веришь нет, сделал точно так же как и написал, все работает почему то...
Могу исходники выложить



Верю. :)
Не спорю, но я же говорю, раз на раз. Вот допустим такой код

 
Код:
CWnd *wnd = (CWnd *)param;
wnd->GetParentFrame();

в Debug'е "ругнется" assert'ом. А в релизе просто вернет NULL.
Просто я не сторонник подобного метода, так как при расширении кода могут возникнуть проблемы, на исправление которых может уйти слишком много времени. Поэтому по-моему лучше заранее потратить немного больше сил, но написать расширяемый код.

[OFFTOP]
Сталкивался однажды, когда получил уже написанный довольно большой код с использованием CSocket и одного потока. Протокол передачи данных переписывать с нуля не хотелось, поэтому для решения определенной проблемы решил поиграться с CSocket в отдельном потоке. "Наигравшись" понял, что перепиши я протокол заново с нуля, ушло бы гораздо меньше времени. Зато опыт :)
Извините за offtop
[/OFFTOP]
87
04 сентября 2008 года
Kogrom
2.7K / / 02.02.2008
MFC не знаю - обхожусь WIN32 API. Там эту проблему решал так: передавал из потока нужному окну сообщение, что нужно обновить данные. Например:
Код:
// Определяем нужное событие:

enum {UM_THREAD_DONE = WM_USER + 1};
...
// Шлём из потока сообщение:
...
PostMessage(dialogHwnd, UM_THREAD_DONE, 0, 0);
...
// Обрабатываем в нужном окне

    switch (message)
    {
    case UM_THREAD_DONE:
        OnUmMessage(hwnd);
        break;
318
05 сентября 2008 года
nof
193 / / 03.04.2006
Цитата: Kogrom
MFC не знаю - обхожусь WIN32 API. Там эту проблему решал так: передавал из потока нужному окну сообщение, что нужно обновить данные. Например:
Код:
// Определяем нужное событие:

enum {UM_THREAD_DONE = WM_USER + 1};
...
// Шлём из потока сообщение:
...
PostMessage(dialogHwnd, UM_THREAD_DONE, 0, 0);
...
// Обрабатываем в нужном окне

    switch (message)
    {
    case UM_THREAD_DONE:
        OnUmMessage(hwnd);
        break;


Да, вот это отличный вариант. Спасибо!

Цитата: oxotnik333
Вот веришь нет, сделал точно так же как и написал, все работает почему то...
Могу исходники выложить


Вопрос первоначально о функции UpdateData(). В debug режиме программа падает, если вызвать её из потока...

11
05 сентября 2008 года
oxotnik333
2.9K / / 03.08.2007
Цитата: nof

Вопрос первоначально о функции UpdateData(). В debug режиме программа падает, если вызвать её из потока...



В потоке можно вызывать любую ф-ю, другой вопрос будет ли она работать с валидными данными или будет брать битые указатели. Возможно она обращается не к валидным данным, тут уже надо смотреть весь алгоритм целиком.

ЗЫ: Через SendMessage можно сделать многое, но не все

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог