Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
2 / 2 / 0
Регистрация: 13.08.2021
Сообщений: 40
1

Получение ID потока объектов TThread

17.02.2022, 13:36. Показов 1369. Ответов 4
Метки нет (Все метки)

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

Проблема вот в чём. Есть класс, который хранит список существующих потоков. В нём есть вектор, хранящий указатели на эти объекты:
C++
1
std::vector<TThread*> ThreadList;
И функция удаления:
C++
1
2
3
4
5
6
7
8
9
10
11
void ThreadQueue::Erase(unsigned int ID)
{
    for (std::vector<TThread*>::iterator iElem = ThreadList.begin(); iElem != ThreadList.end(); iElem++)
    {
        if (*(*iElem)->ThreadID == ID)
        {
            ThreadList.erase(iElem);
            return;
        }
    }
}
Проблема в функции удаления. Как можно было сразу догадаться, алгоритм заключается в поиске нужного ID потока через итераторы с помощью перебора всех хранящихся объектов. Но при комплияции возникает следующая ошибка в условии оператора if:

[bcc32 Error] ThreadQueue.cpp(18): E2062 Invalid indirection
Full parser context
ThreadQueue.cpp(15): parsing: void ThreadQueue::Erase(unsigned int)

Видимо, проблема в неправильном разыменовании указателя. Здесь оно двойное. Разыменовывать один раз пробовал, помощник кода в таком случае вообще не мог найти функцию ThreadID, да и вообще ни одной функции не нашёл. А при двойном разыменовании функция находится, но выскакивает такая ошибка. Но в чём может быть проблема? Ведь разыменовывая итератор, я по сути дела получаю указатель, который при работе с объектами разыменовывать нет необходимости, если я хочу обратиться к методам этого объекта. Как можно решить эту проблему?

P.s. и вопрос не по теме. Есть какие-либо другие способы оптимизации функции удаления? Без перебора всех объектов и экономии ресурсов компьютера. Хотя, возможно, в этом нет никакой необходимости, но было бы интересно посмотреть на другие варинты
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.02.2022, 13:36
Ответы с готовыми решениями:

Дождаться завершения потока TThread
Есть поток TThread под названием autoupdate и я зщ как после его вызова дождатся его завершения и...

Определить состояние потока TThread
Как узнать создан ли поток и в каком он состаянии: закочен или еще выполняется? Думал по...

Реализация на базе TThread потока с timeout'ом
Реализация прибития потока по timeout'у у меня сейчас реализовано следующим способом. Имеется окно...

Корректное освобождение памяти при принудительном завершении потока TThread
У меня в отдельном потоке выполняются некоторые вычисления. В процессе выполнения этой функции...

4
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
32854 / 21188 / 8151
Регистрация: 22.10.2011
Сообщений: 36,440
Записей в блоге: 8
17.02.2022, 16:50 2
По идее (в нормальной реализации C++) можно было бы сделать так:
C++
1
2
3
4
5
6
7
void ThreadQueue::Erase(unsigned int ID)
{
    ThreadList.erase(
        std::remove_if(std::begin(ThreadList), std::end(ThreadList), [ID](TThread *th) {return th->ThreadID == ID;}), 
        std::end(ThreadList) 
    );
}
, а в C++20 - вообще
C++
1
2
3
4
void ThreadQueue::Erase(unsigned int ID)
{
    std::erase_if(ThreadList, [ID](TThread *th) { return th->ThreadID == ID; });
}
, но вопрос - в том, что именно позволит сделать твоя версия Билдера...
1
2 / 2 / 0
Регистрация: 13.08.2021
Сообщений: 40
18.02.2022, 00:01  [ТС] 3
И ни один в моей версии Билдера не работает) использую версию 10.4, вроде не такая уж и старая.
Компилятор выдаёт такую ошибку:
[bcc32 Error] ThreadQueue.cpp(17): E2316 'remove_if' is not a member of 'std'
Возможно, придётся искать нужные методы и отдельно разбираться в библиотеке stl, пробуя разные варианты
0
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
32854 / 21188 / 8151
Регистрация: 22.10.2011
Сообщений: 36,440
Записей в блоге: 8
18.02.2022, 00:16 4
C++
1
#include <algorithm>
, надеюсь, подключен? Потому что remove_if однозначно доступен в Билдере, даже под BCB6, правда, без лямбды, с функтором. Но если бы это было это из-за лямбды - то ошибка должна была быть другая.
1
2 / 2 / 0
Регистрация: 13.08.2021
Сообщений: 40
18.02.2022, 23:13  [ТС] 5
Инклюда не было) подозревал, что может быть проблема именно в неподключенной библиотеке, но не смог найти эту информацию в интернете. Хотя может быть плохо искал. Сейчас то уже вижу список всех этих функций и среди них та, которую вы привели в пример - remove_if.

Но теперь другая проблема - компилятор жалуется на begin и end в аргументах remove_if. Пришлось вызывать их как функции непосредственно через контейнер, то есть через обращение к его методам, а не как передача в качестве аргумента в саму функцию begin или end. То есть так:
C++
1
ThreadList.begin();
Далее, компилятор жаловался на обозначение [ID]. Это ведь и есть лямбда? Функтор, насколько я понимаю, это передача в функцию в качестве аргумента адрес другой функции, которая возвращает булево значение. С теорией у меня пока всё сложно). Вышло как-то так:
C++
1
2
3
4
bool Equals(TThread *Thr)
{
    return Thr->ThreadID == CurID;
}
Но чтобы сравнивать ID нужного потока с тем ID, который мы ищем, нужно было добавить глобальную переменную, которой мы присваиваем значение, которое мы передаем функции Erase (то есть максимально сильно запутать программу):
C++
1
2
3
4
5
6
7
unsigned int CurID;
 
void ThreadQueue::Erase(unsigned int ID)
{
    CurID = ID;
    ThreadList.erase(std::remove_if(ThreadList.begin(), ThreadList.end(), Equals));
}
И вот после всех этих модификаций программа заработала. Но пока не было времени её протестировать, так что спасибо за совет, надеюсь, он действительно рабочий.

P.s. Эх, придётся опять учить всю эту stl и весь этот новый и непривычный синтаксис с лямбда фунциями...

Добавлено через 2 минуты
И вообще, использование глобальных переменных - плохой стиль. Хотелось бы от него избавиться, вот только не знаю как. Либо другая функция, либо каким-то другим нетривиальным способом можно сравнивать её в функции Equals. Нужно будет поискать информацию и подумать. Благодарю за наводку
0
18.02.2022, 23:13
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.02.2022, 23:13
Помогаю со студенческими работами здесь

ShellExecute из потока Tthread
Здравствуйте. Нужно в потоках вызывать функцию Shellexecute для выполнения команд. Грубо говоря,...

Как правильно получить данные от потока TThread?
Есть N потоков одного класса (потомок TThread), которые генерируют строку каждые 5 секунд. Как...

Как получить доступ к методу TThread из основного потока?
Добрый день. Есть код Основной поток: unit uMain; interface uses ........ type ...

Не могу создать Ole объект при создании нового потока TThread
Я создаю экземпляр этого класса interface uses ...

Создать два потока: первый - средствами Windows API, второй - с использованием класса TThread
Создать два потока. Первый поток создать средствами Windows API, второй с использованием класса...

Получение значений свойств объектов класса в векторе этих объектов
У меня есть вектор TImageb и мне нужно получить значения Tag каждого объекта этого вектора делаю...

Получение значений из потока
Запускаю поток, в котором пытаюсь получить значение текущего статуса выполнения. Явно я что-то...


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru