Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Как прервать поток и вызвать его же заново?  (Прочитано 15023 раз)
0 Пользователей и 3 Гостей смотрят эту тему.
dark_rain
Помогающий

ua
Offline Offline
Пол: Мужской

« : 25-08-2011 09:31 » 

Имеется небольшое приложение на WTL, используется boost::thread. При выборе директории через стандартный диалог считывается информация о файлах внутри и выводиться в список, это сделано в отдельном потоке для того, что бы был доступен GUI. Предположим мне нужно выбрать другу директорию и считывать информацию о ее файлах этим же потоком, но ведь он уже выполняется. Как мне его прервать и запустить снова с параметрами другой директории?

Итак для большей наглядности приведу несколько ф-ций:

По нажатию на кнопочку "FILL" вызываеться диалог "Browse for folder"

Код:
LRESULT CMainDlg::OnFill(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
{
TCHAR szPath[MAX_PATH];
BOOL res = FALSE;

LPMALLOC pMalloc;
if (::SHGetMalloc(&pMalloc) == NOERROR)
{
BROWSEINFO bi;
::ZeroMemory(&bi,sizeof bi);
bi.ulFlags = BIF_RETURNONLYFSDIRS;
LPITEMIDLIST pidl = ::SHBrowseForFolder(&bi);
if (pidl != NULL)
{
if (::SHGetPathFromIDList(pidl,szPath))
{
if (szPath) //если нажата кнопка ОК
{
TheThread (szPath); //вызывается отдельный поток

}
}
}
}
return 0;
}
}

вот что делает этот самый поток

Код:
int CMainDlg::TheThread (const CString& pth)
{
boost::thread my_thread(boost::bind(&CMainDlg::ReadFilesInf, this, pth)); //вызывается метод ReadFilesInf с параметром szPath
return 0;

}


вот сам метод ReadFilesInf

Код:
int CMainDlg::ReadFilesInf (const CString& pth)
{
int userReplay;

path p (pth.GetString());


/* привожу для наглядности
struct FileInformation
{
CString fName;
CString fPath;
CString size;
CString time;
};*/


FileInformation information;

EnterCriticalSection(&cs);

recursive_directory_iterator end;
recursive_directory_iterator it(p);
while (it != end)
{
try
{
path curPath(*it);
if (is_regular_file(curPath))
{
CTime w_time = last_write_time(*it);
CString str = w_time.Format( L"%d, %b, %Y, %H:%M" );
LPCTSTR timeCreation = str;

std::wstring fileSizeStr = boost::lexical_cast<std::wstring>(file_size(curPath));
std::wstring filePathStr = boost::lexical_cast<std::wstring>(curPath);


information.fName = curPath.leaf().c_str();
information.fPath = curPath.branch_path().c_str();
information.size = fileSizeStr.c_str();
information.time = timeCreation;

list_.fileList_.push_back (information); //list_ это мой виртуальный список   fileList_ это вектор который хранит информацию о файлах
list_.SetItemCountEx(list_.fileList_.size(), LVSICF_NOINVALIDATEALL);

}
++it;
}
catch (boost::system::system_error const& e)
{
if (e.code().value() != ERROR_ACCESS_DENIED)
{
throw;
}

}
}
LeaveCriticalSection(&cs);

return 0;
}

П.С. Господа приношу извинения если не достаточно доступно изложил суть вопроса.
Записан
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 25-08-2011 09:42 » 

а в чем проблема, послать потоку сигнал о досрочном завершении, дождаться его завершения и перезапустить?
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
zubr
Гость
« Ответ #2 : 25-08-2011 09:49 » 

1. В рекурсивный цикл потока ввести внешнюю булеву переменную. Рекурсивный цикл при каждой итерации проверяет ее состояние.
2. Перед запуском потока проверить его состояние функцией WaitForSingleObject по короткому таймауту. Если функция вышла по таймауту, значит поток уже запущен, тогда устанавливаем нашу булеву переменную на выход из рекурсии, опять вызываем WaitForSingleObject с длительным таймаутом или INFINITE, чтобы дождаться завершения потока.
3. Запускаем новый поток.
Записан
dark_rain
Помогающий

ua
Offline Offline
Пол: Мужской

« Ответ #3 : 25-08-2011 09:55 » 

а в чем проблема, послать потоку сигнал о досрочном завершении, дождаться его завершения и перезапустить?
Я то понимаю это в теории) Просто я только учусь и с кодированием моих теоретических знаний у меня возникают накладки Улыбаюсь

1. В рекурсивный цикл потока ввести внешнюю булеву переменную. Рекурсивный цикл при каждой итерации проверяет ее состояние.
2. Перед запуском потока проверить его состояние функцией WaitForSingleObject по короткому таймауту. Если функция вышла по таймауту, значит поток уже запущен, тогда устанавливаем нашу булеву переменную на выход из рекурсии, опять вызываем WaitForSingleObject с длительным таймаутом или INFINITE, чтобы дождаться завершения потока.
3. Запускаем новый поток.

Можно пример кода или ссылку на какой либо ресурс содержащий его?
Записан
zubr
Гость
« Ответ #4 : 25-08-2011 10:03 » 

dark_rain, ту вроде все просто. Что именно непонятно? Как ввести внешнюю переменную или как использовать WaitForSingleObject?
Записан
dark_rain
Помогающий

ua
Offline Offline
Пол: Мужской

« Ответ #5 : 25-08-2011 10:24 » 

zubr, на сколько я осведомлен, рекурсия - вызов самого себя. Где у меня рекурсивный цикл потока? Он вызывается пользователем по нажатию кнопочки "ОК". 
Записан
zubr
Гость
« Ответ #6 : 25-08-2011 10:49 » 

dark_rain, у меня нет времени и желания ковыряться в твоем коде. Я тебе описал алгоритм реализации твоего вопроса. Тем более код, который ты выложил, далеко не полон, к примеру, что за тип path или recursive_directory_iterator?
Если уж исходить из твоего кода, то итерации происходят только в одном месте (правда я не знаю что у тебя под "капотом" в конструкторе типа path) - while (it != end). Что мешает сделать: while( (it != end) && (!bTerminated)), где bTerminated - внешняя булева переменная.
Записан
dark_rain
Помогающий

ua
Offline Offline
Пол: Мужской

« Ответ #7 : 25-08-2011 11:33 » 

path и recursive_directory_iterator это классы boost::filesystem. Спасибо и на этом. Попробую разобраться.
« Последнее редактирование: 25-08-2011 14:25 от dark_rain » Записан
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 25-08-2011 14:19 » new

zubr, а WFSO для хендла потока нельзя делать?
в винде вроде дозволяется, правда не знаю как с бустом и линуксом.
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
zubr
Гость
« Ответ #9 : 25-08-2011 14:42 » 

Ochkarik, ну я в общем то и имел в виду использование хендла потока. Я буст тоже не юзал, там вроде есть что то типа boost::thread.wait
Записан
Ochkarik
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 25-08-2011 14:50 » 

ну да. пардон, не уловил сразу)
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #11 : 26-08-2011 04:16 » 

dark_rain, ИМХО проще грохнуть поток чем, останавливать, востанавливать не стоит игра свеч, если этот поток обслуживает GUI те ms которые уйдут на эту операцию пользователь даже не заметит

http://www.boost.org/doc/libs/1_47_0/doc/html/thread/thread_management.html

функциями прирывания никогда не польовался, обычно в функцию потока прокидывал volitile переменную stop, поток её периодически смотрел и выходил, если она true
синхронизация этой переменной нафиг не нужна
если надо завершить поток, то снаружи делаем
Код: (C++)
stop = true;
thread.join();
хотя в те времена небыло boost::thread::interrupt, так что можешь её попробовать
Записан

Странно всё это....
dark_rain
Помогающий

ua
Offline Offline
Пол: Мужской

« Ответ #12 : 26-08-2011 13:50 » 


хотя в те времена небыло boost::thread::interrupt, так что можешь её попробовать


Спасибо! Именно с помощью этого и реализовал.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines