Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> WaitForSingleObject лочит тред? 
V
    Опции темы
mrgloom
Дата 9.7.2012, 12:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



такое ощущение, что WaitForSingleObject в основном процессе блокирует выполнение кода в созданном треде.

т.е. я например делаю
Код

::SetEvent(m_StopThread);

хочу чтобы тред остановился ,а тред должен выставить ивент когда закончится.

Код

            if(::WaitForSingleObject(pthis->m_StopThread, 0) == WAIT_OBJECT_0)
            {

                // Set event
                ::SetEvent(pthis->m_WaitThread);

                LogMsg(_T("return from thread \r\n"));
                return 0;
            }


и ожидаю
Код

        while(::WaitForSingleObject(m_WaitThread, 0)!= WAIT_OBJECT_0)
            Sleep(10000);

или так 

Код

::WaitForSingleObject(m_WaitThread, INFINITE);



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

while(::WaitForSingleObject(m_test, 0)!= WAIT_OBJECT_0)
            Sleep(10000); 

причем если WaitForSingleObject убрать, то в тред нормально заходит и ::SetEvent(m_StopThread); и условие тоже нормально схватывает.
но мне надо не просто отправить команду треду завершится но еще и  подождать пока завершится тред.
PM MAIL   Вверх
Randajad
Дата 9.7.2012, 12:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



(std|boost)::thread и не пишите платформозависимый код.
PM MAIL   Вверх
baldina
Дата 9.7.2012, 13:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

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



у WaitForSingleObject второй параметр - время ожидания. Вам, по видимому туда надо передавать константу INFINITE. Если передается 0, то WaitForSingleObject ничего не ждет, а сразу возвращает текущее состояние.
Однако хотелось бы увидеть возвращаемое значение, Вы его нигде не анализируете, а оно может быть разным. Например WAIT_FAILED.
Были ли m_StopThread и m_WaitThread созданы при помощи CreateEvent() ?

 smile а причем тут общие вопросы с++?
PM MAIL   Вверх
mrgloom
Дата 9.7.2012, 15:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(baldina @  9.7.2012,  13:28 Найти цитируемый пост)
у WaitForSingleObject второй параметр - время ожидания. Вам, по видимому туда надо передавать константу INFINITE. Если передается 0, то WaitForSingleObject ничего не ждет, а сразу возвращает текущее состояние.


я и так пробовал, 
Код

::WaitForSingleObject(m_WaitThread, INFINITE);


Цитата

Однако хотелось бы увидеть возвращаемое значение, Вы его нигде не анализируете, а оно может быть разным. Например WAIT_FAILED.

так дело в том что значения и не возвращается ,а просто висит всё на этой функции.

Цитата(baldina @  9.7.2012,  13:28 Найти цитируемый пост)
Были ли m_StopThread и m_WaitThread созданы при помощи CreateEvent() ?

ага
Код

m_StopThread = CreateEvent(0, TRUE, FALSE, 0);
m_WaitThread = CreateEvent(0, TRUE, FALSE, 0);


в бусте, что то не нашел аналога ивенту и для завершения там только .join? у меня там в треде цикл и надо его прервать на очередной итерации записав текущее переменные.

Это сообщение отредактировал(а) mrgloom - 9.7.2012, 15:35
PM MAIL   Вверх
Randajad
Дата 9.7.2012, 16:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



std::atomic в помощь. Делаете, скажем, булевую переменную - выставляете ее в true, если надо прервать. В цикле в потоке проверяете ее.
PM MAIL   Вверх
mrgloom
Дата 9.7.2012, 16:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



попробовал буст+ булевые переменные в классе


так запускаю
Код

m_StopThread= false;
        m_WaitThread= false;
        boost::thread workerThread(&CControlDlg::GetFrame,this);   

так останавливаю
Код

        m_StopThread=true;
        while(!m_WaitThread)
            Sleep(1000);


в теле треда

Код

if(m_StopThread)
            {
                m_WaitThread=true;

                LogMsg(_T("return from thread \r\n"));
                return;
            }
            else
            {
                        //do work
                        }


и всё равно на while(!m_WaitThread) всё виснет и в треде почему то ничего не выполняется.

Добавлено @ 16:49
не заметил ответа, пока писал.

std::atomic? в каких то источниках пишут еще volatile bool, а простая булевая переменная таит в себе какие то опастности?

Добавлено @ 16:58
попробовал volatile bool результат тот же. а std::atomic это же что то новое как и std::thread, не?

Это сообщение отредактировал(а) mrgloom - 9.7.2012, 16:59
PM MAIL   Вверх
feodorv
Дата 9.7.2012, 23:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

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



Цитата(mrgloom @  9.7.2012,  13:27 Найти цитируемый пост)
хочу чтобы тред остановился ,а тред должен выставить ивент когда закончится.

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

WaitForSingleObject( hThread, INFINITE);


Цитата(mrgloom @  9.7.2012,  13:27 Найти цитируемый пост)
причем если WaitForSingleObject убрать

Я не понял, какой именно... Да и вообще не понятно, что происходит в программе (в основном потоке и в созданном). У Вас есть возможность сбрасывать логи, так почему бы ей не воспользоваться? Вставьте в проблемные части кода немного выдачи, да проанализируйте её... Я вот, например, не уверен, что
Цитата(mrgloom @  9.7.2012,  13:27 Найти цитируемый пост)
           if(::WaitForSingleObject(pthis->m_StopThread, 0) == WAIT_OBJECT_0)

хоть когда-нибудь вернёт WAIT_OBJECT_0.... А если возвращает, то почему не выдаёт
Цитата(mrgloom @  9.7.2012,  13:27 Найти цитируемый пост)
                LogMsg(_T("return from thread \r\n"));

??? Или выдаёт? Короче, нужны подробности, ничего не ясно...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
mrgloom
Дата 10.7.2012, 09:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



ну да можно без ивента
попробовал так. постоянно  WAIT_TIMEOUT, в теле треда никакой активности.
Код

while(::WaitForSingleObject(m_WorkWinThread->m_hThread, 0)!= WAIT_OBJECT_0)
        {
            if(::WaitForSingleObject(m_WorkWinThread->m_hThread, 0)== WAIT_TIMEOUT)
                int f=0;
            if(::WaitForSingleObject(m_WorkWinThread->m_hThread, 0)== WAIT_FAILED)
                int f=0;
            if(::WaitForSingleObject(m_WorkWinThread->m_hThread, 0)== WAIT_ABANDONED)
                int f=0;
            Sleep(10000);
        }



Цитата

причем если WaitForSingleObject убрать

Я не понял, какой именно... Да и вообще не понятно, что происходит в программе (в основном потоке и в созданном). У Вас есть возможность сбрасывать логи, так почему бы ей не воспользоваться? Вставьте в проблемные части кода немного выдачи, да проанализируйте её... Я вот, например, не уверен, что
Цитата(mrgloom @  9.7.2012,  13:27 )
           if(::WaitForSingleObject(pthis->m_StopThread, 0) == WAIT_OBJECT_0)

хоть когда-нибудь вернёт WAIT_OBJECT_0.... А если возвращает, то почему не выдаёт


я выше написал как вызываю, есть кнопка на форме старт и пауза, на старт тред начинает исполнение, на паузу выставляется ивент остановить тред, который на каждой итерации в цикле треда проверяется, потом надо дождатся когда тред закончится и вот тут то и вылезает проблема, т.к. всё зависает на  WaitForSingleObject.  может это как то связано с формой? или ивент каким то образом лочится?
причем если без WaitForSingleObject, то ивент в треде нормально определяется и тред завершается, только получается основной поток его не ждет.

Добавлено через 14 минут и 45 секунд
хммм попробовал 

Код

        ::SetEvent(m_StopThread);
        Sleep(10000); //время заведомо больше чем выполняется 1 цикл в треде


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

Это сообщение отредактировал(а) mrgloom - 10.7.2012, 09:36
PM MAIL   Вверх
mrgloom
Дата 10.7.2012, 09:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



попробовал так, всё тоже самое, изменение приоритета не помогает.

Код

m_WorkWinThread= AfxBeginThread(CControlDlg::GetFrame,this,THREAD_PRIORITY_TIME_CRITICAL);

PM MAIL   Вверх
baldina
Дата 10.7.2012, 11:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

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



запустите такую программку
Код

#include <windows.h>
#include <process.h>
#include <iostream>

HANDLE ev1 = CreateEvent (0, FALSE, FALSE, 0);
HANDLE ev2 = CreateEvent (0, FALSE, FALSE, 0);

void thread1 (void*) {
  std::cout << "thread1 started\n";
  DWORD result = WaitForSingleObject (ev1, INFINITE);
  std::cout << "ev1 signaled with " << result << std::endl;
  SetEvent (ev2);
  std::cout << "thread1 exiting\n";
}

int main () {
  std::cout << "main started\n";
  _beginthread (thread1, 0, 0);
  SetEvent (ev1);
  DWORD result = WaitForSingleObject (ev2, INFINITE);
  std::cout << "ev2 signaled with " << result << std::endl;
  std::cout << "main exiting\n";
}

result в обоих случаях должен быть равным 0 (это и есть WAIT_OBJECT_0)
PM MAIL   Вверх
feodorv
Дата 10.7.2012, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

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



Цитата(mrgloom @  10.7.2012,  10:49 Найти цитируемый пост)
CControlDlg::GetFrame

А что за функция? Как описана?


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
mrgloom
Дата 10.7.2012, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



попробовал
Код

void thread1 (void*) 
{
    DWORD result = WaitForSingleObject (ev1, INFINITE);
    SetEvent (ev2);
}
void test_func()
{
    _beginthread (thread1, 0, 0);
    SetEvent (ev1);
    DWORD result = WaitForSingleObject (ev2, INFINITE);
}


и всё сработало и меня натолкнуло на мысль а не попробовать ли CControlDlg::GetFrame без класса и попробовал и оно заработало ,а теперь остается  вопрос, почему когда функция внутри класса, то она не работает?  может это связано с тем что если объявлять в классе, то для передачи в AfxBeginThread её надо объявлять как static?  а может заработало потому что я ивенты объявил глобально, а не в классе?


функция CControlDlg::GetFrame  сейчас там просто цикл с слипом для тестирования, типа имитация работы, начальное значения от куда начинать цикл берется из класса.

Это сообщение отредактировал(а) mrgloom - 10.7.2012, 12:59
PM MAIL   Вверх
baldina
Дата 10.7.2012, 13:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

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



CControlDlg::GetFrame вызывалась без объекта? тогда просто повезло, что оно не плюхнулось.

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


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

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



Цитата(mrgloom @  10.7.2012,  13:56 Найти цитируемый пост)
почему когда функция внутри класса

Если функция описана внутри класса, то она неявно имеет ещё один аргумент. В результате 
Код

UINT CControlDlg::GetFrame(LPVOID pParam)

превращается в 
Код

UINT GetFrame@CControlDlg@@args( CControlDlg *this, LPVOID pParam)



Цитата(baldina @  10.7.2012,  14:09 Найти цитируемый пост)
CControlDlg::GetFrame вызывалась без объекта?

Вызывалось, так как первым аргументом AfxBeginThread шла функция, а в этом случае AfxBeginThread не знает, что она из какого-то класса... Компилятор, кстати, должен бы выдать предупреждение...

Это сообщение отредактировал(а) feodorv - 10.7.2012, 13:30


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
mrgloom
Дата 10.7.2012, 15:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(feodorv @  10.7.2012,  13:15 Найти цитируемый пост)
почему когда функция внутри класса

Если функция описана внутри класса, то она неявно имеет ещё один аргумент. В результате 
код C++
1:
UINT CControlDlg::GetFrame(LPVOID pParam)

превращается в 
код C++
1:
UINT GetFrame@CControlDlg@@args( CControlDlg *this, LPVOID pParam)

ну и какой из этого вывод?

Цитата(baldina @  10.7.2012,  13:09 Найти цитируемый пост)
CControlDlg::GetFrame вызывалась без объекта? тогда просто повезло, что оно не плюхнулось.

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


Это сообщение отредактировал(а) mrgloom - 10.7.2012, 15:55
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




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


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

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