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

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Как грамотно прервать выполнение потока  (Прочитано 16316 раз)
0 Пользователей и 3 Гостей смотрят эту тему.
SSW
Гость
« : 01-12-2004 14:54 » 

Windows / VC++ 6.0 / MFC

Есть функция
Код:

UINT ThreadProc(LPVOID param)
{
 
while (TRUE)
{
   ...

 // Wait for notification.
    dwWaitStatus = WaitForMultipleObjects(1, dwChangeHandles, FALSE, INFINITE);
      switch (dwWaitStatus)
      {
         case WAIT_OBJECT_0:
 
         // A file was created or deleted in the directory.
         // Refresh this directory and restart the notification.
 
            AfxMessageBox("YES !!!!!!!!!!!!!!!!!");
            break;
        default:
            ExitProcess(GetLastError());
      }


/*********/
}

Я делаю ее в потоке

Код:
    AfxBeginThread(ThreadProc, this);

Вопрос, как грамотно прервать выполнение такой функции и завершить поток?
« Последнее редактирование: 02-12-2007 18:58 от Алексей1153++ » Записан
npak
Команда клуба

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

« Ответ #1 : 01-12-2004 15:11 » 

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

В потоке
Код:
    HANDLE SyncArray = { ChangeHandle, ExitEvent };
    dwWaitStatus = WaitForMultipleObjects(2, SyncArray, FALSE, INFINITE);
    switch (dwWaitStatus) {
         case WAIT_OBJECT_0:
 
         // A file was created or deleted in the directory.
         // Refresh this directory and restart the notification.
 
            AfxMessageBox("YES !!!!!!!!!!!!!!!!!");
            break;
        case WAIT_OBJECT_1:
 
            // Killed
 
            AfxMessageBox("I'm dying !!!!!!");
            ExitThread(0);
            break;
        default:
            ExitProcess(GetLastError());
      }

Во внешнем мире:
Код:
   SetEvent( ExitEvent );
прывает исполнение потока
« Последнее редактирование: 02-12-2007 19:01 от Алексей1153++ » Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
SSW
Гость
« Ответ #2 : 01-12-2004 16:40 » 

Если я правильно понял, надо добавить хендел потока в масив, и потом ожидать срабатывания от WaitForMultipleObjects.

Сделал так:
Код:
	threadHandle = GetCurrentThread();

DWORD dwWaitStatus;           
    HANDLE dwChangeHandles[2];
// Watch the directory for file creation and deletion.

   dwChangeHandles[0] = threadHandle;
   
   dwChangeHandles[1] = FindFirstChangeNotification(
      FolderName,                         // directory to watch
      FALSE, // do not watch subtree
      FILE_NOTIFY_CHANGE_FILE_NAME); // watch file name changes
// Change notification is set. Now wait on both notification
// handles and refresh accordingly.
   while (TRUE)
   {
   // Wait for notification.

      dwWaitStatus = WaitForMultipleObjects(2, dwChangeHandles, FALSE, INFINITE);
 
      switch (dwWaitStatus)
      {
         case WAIT_OBJECT_0:
 
         // A file was created or deleted in the directory.
         // Refresh this directory and restart the notification.
 
            AfxMessageBox(" YES    !!!!!!!!!!!!!!!!!!!!!");

if ( FindNextChangeNotification(dwChangeHandles[0]) == FALSE)
ExitProcess(GetLastError());
            break;

         case WAIT_OBJECT_0+1:
 
            // Killed
 
            AfxMessageBox("I'm dying !!!!!!");
            ExitThread(0);
            break;


        default:
            ExitProcess(GetLastError());
      }
   }
}

Как только поток получает управления сразу вываливается.
Пошаговое выполнение заканчивается тем, что VC++ выдает:

The thread 0xFC0 has exited with code 6 (0x6).
« Последнее редактирование: 02-12-2007 19:02 от Алексей1153++ » Записан
npak
Команда клуба

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

« Ответ #3 : 01-12-2004 17:43 » 

SSW, не, не так.

Перед созданием потока надо сделать событие (CreateEvent) и передать его в процедуру потока

Код:
obj->ThreadExitEvent = CreateEvent( ... );
AfxCreateThread(..., obj);

в потоке
Код:
dwChangeHandles[0] = arg->ThreadExitEvent;

Когда надо будет нить закончить
Код:
SetEvent(obj->ThreadExitEvent);
« Последнее редактирование: 02-12-2007 19:03 от Алексей1153++ » Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
SSW
Гость
« Ответ #4 : 02-12-2004 07:57 » 

Ух !

Наконец то заработало !

ОГРОМНОЕ спасибо !
Записан
npak
Команда клуба

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

« Ответ #5 : 02-12-2004 09:24 » 

SSW, Улыбаюсь
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Bork
Гость
« Ответ #6 : 02-04-2005 02:22 » new

А еще грамотнее - вместо ExitThread(0) использовать return 0 Улыбаюсь
Записан
RXL
Технический
Администратор

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

WWW
« Ответ #7 : 02-04-2005 08:40 » 

Bork, это равноценно, но ExitThread() информативнее - сразу видно, что тут не просто выход из ф-ии.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Bork
Гость
« Ответ #8 : 09-04-2005 02:43 » 

Bork, это равноценно, но ExitThread() информативнее - сразу видно, что тут не просто выход из ф-ии.

Цитата (Рихтер, глава 6):

"Поток можно завершить принудительно, вызвав:

VOID ExitThread(DWORD dwExitCоde);

При этом освобождаются все ресурсы операционной системы, выделенные данному потоку, но C/C++ - pеcypcы (например, объекты, созданные из С++-классов) не очищаются. Именно поэтому лучше возвращать управление из функции потока, чем самому вызывать функцию ExitThread."

т.е. деструкторы локальных объектов вызваны не будут. так что не равноценно это ...
Записан
RXL
Технический
Администратор

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

WWW
« Ответ #9 : 09-04-2005 20:50 » 

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/exitthread.asp

Согласен. Но это касается не только автоматических объектов, но и динамических и динамически выделенной памяти. То же самое произойдет и при завершении потока из другого потока - подмечу, что тут уже return ничем не поможет.

При штатном выходе инициировать вызов деструкторов можно поместив создание объектов в блок, а ExitThread() за блоком.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines