Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.98/40: Рейтинг темы: голосов - 40, средняя оценка - 4.98
7 / 7 / 3
Регистрация: 04.06.2015
Сообщений: 189

Как правильно завершать поток?

01.06.2018, 09:41. Показов 8541. Ответов 22
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
есть код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include "stdafx.h"
DWORD WINAPI PoolThread(LPVOID);
 
int _tmain(int argc, _TCHAR* argv[])
{
    while(1)
    {
        HANDLE g_hPoolThread = CreateThread(NULL, 0, PoolThread, NULL, 0, NULL);
        Sleep(10);
        ::TerminateThread(g_hPoolThread, NO_ERROR);
    }
    return 0;
}
 
 
 
DWORD WINAPI PoolThread(LPVOID)
{
    while(1)
    {
        double a,s,d,f,g,h,j,k,l,q,w,e,r,t,y,u,i,o,p;
 
        
    }
    return 0;
}
Почему при увеличивается память процесса (смотрю в Диспетчере задач). Если же убрать цикл из потока то память не увеличивается. Следовательно не чистится при вызови функции TerminateThrea.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
01.06.2018, 09:41
Ответы с готовыми решениями:

Как правильно завершить поток, который лочит мьютекс в цикле?
Есть поток, созданный посредствам CreateThread, который в цикле лочит именной мьютекс, ну типа while(1) { OpenMutex(MUTEX_ALL_ACCESS,...

Как завершать потоки?
Создал поток, а завершить немогу. Поток можно завершить четырьмя способами: 1)функция потока возвращает управление; 2)поток...

Как правильно завершать дочерний поток?
Всем доброго времени суток! Есть некий объект в котором запускается дочерний поток и в нем объект. Так вот при завершении основного...

22
2734 / 888 / 331
Регистрация: 10.02.2018
Сообщений: 2,099
01.06.2018, 10:18
Правильнее всего завершать поток с помощью return из функции потока.
Когда функция потока завершена основная программа должна сделать CloseHandle для хендла возвращённого CreateThread.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include "stdafx.h"
#include "windows.h"
 
DWORD WINAPI PoolThread(LPVOID);
 
int _tmain(int argc, _TCHAR* argv[])
{
    bool bNeedStop;
    while(1)
    {
        bNeedStop = false;
        HANDLE g_hPoolThread = CreateThread(NULL, 0, PoolThread, &bNeedStop, 0, NULL);
        Sleep(10);
        //::TerminateThread(g_hPoolThread, NO_ERROR);
        bNeedStop = true; // сообщаем потоку, что нужно завершаться
        WaitForSingleObject(g_hPoolThread, INFINITE); // ждём, когда поток реально завершится
        CloseHandle(g_hPoolThread); // закрываем хендл
    }
    return 0;
}
 
DWORD WINAPI PoolThread(LPVOID pNeedStop)
{
    while (!(*(bool*)pNeedStop))
    {
        double a,s,d,f,g,h,j,k,l,q,w,e,r,t,y,u,i,o,p;
    }
    return 0;
}
1
7 / 7 / 3
Регистрация: 04.06.2015
Сообщений: 189
01.06.2018, 11:24  [ТС]
а если поток создавался без Handle,

CreateThread(NULL, 0, PoolThread, &bNeedStop, 0, NULL);

как его закрывать.

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

Добавлено через 1 минуту
Продолжаю исследовать потоки и завершение из и наткнулся на интересный момент.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include "stdafx.h"
DWORD WINAPI PoolThread(LPVOID);
 
int _tmain(int argc, _TCHAR* argv[])
{
    while(1)
    {
        HANDLE g_hPoolThread = CreateThread(NULL, 0, PoolThread, NULL, 0, NULL);
        Sleep(10);
        ::TerminateThread(g_hPoolThread, NO_ERROR);
    }
    return 0;
}
 
 
 
DWORD WINAPI PoolThread(LPVOID)
{
    while(1)
    {
        WIN32_FIND_DATA wfd;
        HANDLE hFind = FindFirstFile(_T("C:\\*"), &wfd);
        
        
    }
    return 0;
}
После нескольких итерации основного потока он зависает на функции CreateThread при этом поток не создается. Есть ли этому объяснение?
0
2734 / 888 / 331
Регистрация: 10.02.2018
Сообщений: 2,099
01.06.2018, 12:43
Цитата Сообщение от Sierra26 Посмотреть сообщение
а если поток создавался без Handle,
CreateThread(NULL, 0, PoolThread, &bNeedStop, 0, NULL);
как его закрывать.
Ну, а если сделать выделение памяти без присвоения указателя
new int[100];
как потом очистить память?

::TerminateThread убивает поток в произвольном месте исполнения.
Например, есть у вас функция потока
C++
1
2
3
int* ptr = new int[100];
// делать что-нибудь с ptr
delete[] ptr;
::TerminateThread может убить поток после new, но до delete. Память останется выделенной до конца работы программы.
TerminateThread может убить поток в процессе вызова им системных функций, в критических секциях и т.д. и т.п. В общем случае, использование TerminateThread не рекомендуется.
1
Эксперт С++
2924 / 1274 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
01.06.2018, 13:45
Правильно - передать потоку сигнал к благополучному завершению, и подождать, пока поток завершится сам.
0
7 / 7 / 3
Регистрация: 04.06.2015
Сообщений: 189
01.06.2018, 16:17  [ТС]
Ну, а если сделать выделение памяти без присвоения указателя
new int[100];

Даже не задумывался. Понял.

Добавлено через 2 минуты
Правильно - передать потоку сигнал к благополучному завершению, и подождать, пока поток завершится сам. Да ,но допусти есть функции в потоке:
Func1();
Func2();
Func3();
Func4();
Func5();
и каждая выполняется минут по 10 минут. И что после каждого надо вставлять Wait функцию и ждать 10 минут? хотелось бы сразу завершить поток.

Добавлено через 58 секунд
Правильней вот так
while(1)
{
Func1();
Func2();
Func3();
Func4();
Func5();
}
0
Maniac
Эксперт С++
 Аватар для ISergey
1464 / 965 / 160
Регистрация: 02.01.2009
Сообщений: 2,820
Записей в блоге: 1
01.06.2018, 17:38
Цитата Сообщение от Sierra26 Посмотреть сообщение
хотелось бы сразу завершить поток.
что значит завершит сразу? смысл его создавать чтобы потом на пол пути его убить?

Сформулируйте нормально вопрос. Что вы в итоге хотите получить? .
0
7 / 7 / 3
Регистрация: 04.06.2015
Сообщений: 189
01.06.2018, 18:37  [ТС]
создал я его чтобы он циклический проводил заданные операции Func1 и.т.д. А когда захотел из вне убил это поток и не ждал пока он все выполнит и дойдет до Wait функции. И почему на пол пути? Он может выполнить несколько циклов. Задача вот в чем. когда приходит сигнал стоп (BOOL) то нужно уничтожить поток, так как он уже не нужен, и желательно сразу. Как то так.
0
Maniac
Эксперт С++
 Аватар для ISergey
1464 / 965 / 160
Регистрация: 02.01.2009
Сообщений: 2,820
Записей в блоге: 1
02.06.2018, 00:24
Цитата Сообщение от Sierra26 Посмотреть сообщение
создал я его чтобы он циклический проводил заданные операции Func1
просто так обрывать работу потока нельзя, тоесть в то время как будет работать Func1 он умрет и что будет дальше не известно (скорей всего получите испорченный результат, а может вовсе все упадет).

Цитата Сообщение от Sierra26 Посмотреть сообщение
задача вот в чем. когда приходит сигнал стоп (BOOL) то нужно уничтожить поток
Вопрос откуда он должен прийти? по нажатию клавиши или по времени?
0
7 / 7 / 3
Регистрация: 04.06.2015
Сообщений: 189
06.06.2018, 10:05  [ТС]
Вопрос откуда он должен прийти? по нажатию клавиши или по времени? А какая разница? Алгоритм от этого изменится?

Добавлено через 1 минуту
просто так обрывать работу потока нельзя, тоесть в то время как будет работать Func1 он умрет и что будет дальше не известно (скорей всего получите испорченный результат, а может вовсе все упадет).
Пусть умерает. Главное чтобы стек чистился. А при вызови функции TerminateThread он не чистится. Поэтому спрашиваю может кто с танкивался с такой проблемой и решил ее
0
Эксперт С++
2924 / 1274 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
06.06.2018, 13:27
Цитата Сообщение от Sierra26 Посмотреть сообщение
Пусть умерает. Главное чтобы стек чистился.


Засада в том, что при принудительном завершении потока функцией TerminateThread обрабатываемые потоком данные останутся в неопределенном состоянии. Возможно, вообще в некорректном состоянии.
А зачем нужен поток, который гарантированно не обрабатывает никаких данных? Что полезного он делает?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
07.06.2018, 13:48
Цитата Сообщение от Sierra26 Посмотреть сообщение
Пусть умерает. Главное чтобы стек чистился. А при вызови функции TerminateThread он не чистится.
забей на стек, забей на память, забей на данные.
тебе ж главное тред прибить.
так что гори оно все синим пламенем.
0
07.06.2018, 13:58

Не по теме:

Можно ещё свой процесс перезапустить. Кривой стек и прочие проблемы уйдут вместе со старым процессом.

0
7 / 7 / 3
Регистрация: 04.06.2015
Сообщений: 189
07.06.2018, 15:06  [ТС]
на стек бы забил. Но после вызова CreateThread несколько раз зависает и не создает поток.
0
29 / 15 / 10
Регистрация: 07.06.2018
Сообщений: 110
09.06.2018, 11:19
Лучший ответ Сообщение было отмечено Sierra26 как решение

Решение

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

В них проверяешь состояние системного объекта even, созданного функцией CreateEven, с помощью функции WaitForSingleObject c нулевым временем ожидания, выполняешь функцию освобождения локальных ресурсов, задейственных в этом потоке и легально выходишь из потока с помощью оператора return.

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

При этом не забудь тело основной функции потока поставить в следующую конструкцию

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    __try
    {
        __try
        {
                    // Основное тело функции потока
                    // без освобождения локальных ресурсов потока 
        }
        __finally
        {
                    // Освобождение локальных ресурсов потока
        }
    }
    __except(ex)
    {
               // Необходимо чтобы скрыть исключение
               // Можно вывести сообщение о ошибки, а можно этот блок оставить пустым,
               // ничего в нем не делая
    }
Эту же конструкцию можно использовать при обработке ошибок в потоке

Подробнее о использовании этих конструкций смотри по следующей ссылки https://msdn.microsoft.com/ru-... 0%B5%D1%80
1
Maniac
Эксперт С++
 Аватар для ISergey
1464 / 965 / 160
Регистрация: 02.01.2009
Сообщений: 2,820
Записей в блоге: 1
11.06.2018, 14:56
Цитата Сообщение от Melamed Посмотреть сообщение
Если в твоем случае такие функции необходимо поставить не в основную процедуру потока, а в функции, вызывающие этим потоком, то используй исключения.
При этом не забудь тело основной функции потока поставить в следующую конструкцию
и чем это поможет? если прибить поток SEH обработчики не сработают.
0
29 / 15 / 10
Регистрация: 07.06.2018
Сообщений: 110
11.06.2018, 23:28
Цитата Сообщение от ISergey Посмотреть сообщение
и чем это поможет? если прибить поток SEH обработчики не сработают.
В предлагаемом мною методе поток фактически не убивается, а только изменяется его логика выполнения если объект ядра будет в сигнальном состоянии. Поэтому все SEH обработки исключений сработают
0
7 / 7 / 3
Регистрация: 04.06.2015
Сообщений: 189
13.06.2018, 09:59  [ТС]
В принципе так и сделал. Но все равно долго приходится ждать пока завершится поток. Скорей всего просто поставлю на проверку событий во многих местах. Всем спасибо за ответы!
0
475 / 427 / 290
Регистрация: 10.03.2015
Сообщений: 1,782
13.06.2018, 11:15
Sierra26, уже конечно отвечали, но:
Если тебе нужно где-то завершить поток во время выполнения, так вставь в это условие код возврата, и тогда стартовый код корректно подчистит поток и уменьшит счетчик.

Т.е. во входной функции:

C++
1
2
3
4
5
6
7
8
9
10
11
DWORD WINAPI PoolThread(LPVOID)
{
    while(1)
    {
        double a,s,d,f,g,h,j,k,l,q,w,e,r,t,y,u,i,o,p;
        ...
        if (что-то там)
                return 1; //Тогда поток аналогично завершится корректно
    }
    return 0;
}
Иные способы: CloseThread, TerminateThread приведут к некорректному завершению.
0
 Аватар для Kuzia domovenok
4268 / 3327 / 926
Регистрация: 25.03.2012
Сообщений: 12,531
Записей в блоге: 1
13.06.2018, 11:27
Sierra26, судя по вашим же собственным словам, проблема не в потоках, а в том что что-то там слишком долго выполняется. С ней и надо разбираться, а не отвлекаться на потоки.В вашем коде параллельность в принципе не особо нужна.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
13.06.2018, 11:27
Помогаю со студенческими работами здесь

Как правильно завершать действия в MVC?
Здравствуйте. Подскажите, у меня есть mvc система и есть страница с добавлением картинок http://mysite/user_pic. И пользователь нажал...

Как правильно завершать булевую функцию?
bool search(int value, int values, int n) { if (....) return true; else if (....) ... рекурсия else if (....) ... рекурсия...

Как правильно завершать процес даемона ?
Всем привет ! Вот такая проблема - пишу сокет сервер - ну и понятное дело нужно тестить постоянно а у меня такая проблема я например...

Как правильно отправить в поток?
Приветы всем. Помогите разобраться с потоками на простом примере. Ситуация бывает такая, при открытии большого количества файлов,...

Как правильно завершить поток
Всем привет. Что я делаю не так ? Поток запускается и работает хорошо, но вот при завершении программы она не закрывается, а зависает. Как...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru