0 / 0 / 0
Регистрация: 12.03.2018
Сообщений: 14
1

Передача указателя в thread

01.05.2021, 21:32. Показов 2582. Ответов 10

Я из основного потока создаю рабочий поток через вызов функции.
Проблема, что параметр функции уничтожается, до передачи его в поток.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Connect{
};
 
class main{
    main{
        Connect* connect = new Connect();
        run_connect(connect);
    }
 
    void run_connect(Connect* connect){
        std::thread thread(&main::thread_func, this, std::ref(connect));
        thread.detach();
        //Если раскомментировать, то передача connect в thread_func выполняется успешно
        //Sleep(5000);
    }
 
    void thread_func(Connect* connect){
        //Если не выполняется задержка, то здесь некорректный указатель connect
    }
};
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.05.2021, 21:32
Ответы с готовыми решениями:

Передача указателя
Здравствуйте! Форумчане, очень нужна помощь..:cry: В общем ситуация такова: написана программа,...

передача указателя
какой способ передачи указателя наиболее быстрый? int a = 1; int *b= &a;...

C++ 11 передача ссылки в поток thread
Доброго времени суток, возникла такая ситуация. Использую я QT Creator с компилятором MinGW32...

Передача указателя на функцию
Доброго дня Форумчане. Хотелось бы узнать как вызывать функцию получив на нее указатель? пример...

10
610 / 415 / 151
Регистрация: 11.01.2019
Сообщений: 1,745
01.05.2021, 21:40 2
Лучший ответ Сообщение было отмечено Icarus7 как решение

Решение

Цитата Сообщение от Icarus7 Посмотреть сообщение
class main
Это кто ж вас учил такие названия классам давать?

Добавлено через 1 минуту
Цитата Сообщение от Icarus7 Посмотреть сообщение
std::ref(connect)
Этот reference_wrapper обертывает копию указателя, которая разрушается после завершения функции run_connect.

Добавлено через 1 минуту
Цитата Сообщение от Icarus7 Посмотреть сообщение
//Если не выполняется задержка, то здесь некорректный указатель connect
Задержкой вы "продлеваете жизнь" копии указателя connect.
1
0 / 0 / 0
Регистрация: 12.03.2018
Сообщений: 14
01.05.2021, 21:48  [ТС] 3
Согласен. Название класса первое, что пришло в голову))
Заболел ковидом. Стало полегче и решил поизучать новый для меня язык.
Читал про std::ref, но не совсем понял.
Сейчас убрал и вроде как заработало. Буду еще тестировать.
Спасибо большое!
0
6565 / 4550 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
01.05.2021, 21:52 4
Цитата Сообщение от Icarus7 Посмотреть сообщение
Проблема, что параметр функции уничтожается, до передачи его в поток.
У тебя тут целая куча ошибок
Кроме того, как тебе указали выше
Цитата Сообщение от jugu Посмотреть сообщение
Этот reference_wrapper обертывает копию указателя, которая разрушается после завершения функции run_connect.
не надо здесь использовать std::ref, просто передавай значение и всё
Второе - никогда не используй thread.detach()
Третье - постарайся не пользоваться сырыми указателями, используй std::unique_ptr или std::shared_ptr. Иначе будут проблемы. Например в твоём случае - где собирался удалять объект connect?
1
0 / 0 / 0
Регистрация: 12.03.2018
Сообщений: 14
01.05.2021, 21:57  [ТС] 5
Почему нельзя пользоваться detach?
Не понимаю смысла join. Оно останавливает основной поток.
Если мне надо запустить параллельных 10 потоков.

Объект будет удаляться в функции потока thread_func.
0
6565 / 4550 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
01.05.2021, 22:08 6
Лучший ответ Сообщение было отмечено Icarus7 как решение

Решение

Цитата Сообщение от Icarus7 Посмотреть сообщение
Почему нельзя пользоваться detach?
Потому что ты перестаёшь контролировать поток. А это плохо. Откуда ты узнаешь, что он завершился?
Цитата Сообщение от Icarus7 Посмотреть сообщение
Не понимаю смысла join. Оно останавливает основной поток.
Оно ждёт завершения потока. В твоём случае, это следует делать в деструкторе твоего класса

Добавлено через 51 секунду
Цитата Сообщение от Icarus7 Посмотреть сообщение
Объект будет удаляться в функции потока thread_func.
При создании потока может произойти исключение, в этом случае thread_func никогда не запустится.

Добавлено через 1 минуту
Цитата Сообщение от Icarus7 Посмотреть сообщение
Если мне надо запустить параллельных 10 потоков.
Создаёшь массив std::thread и делаешь им всем join, когда это необходимо

Добавлено через 3 минуты
Т.е. твой класс должен выглядеть примерно вот так
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
class main_class
{
public:
    main_class()
    {
        std::unique_ptr<Connect> connect(new Connect());
        run_connect(std::move(connect));
    }
 
    ~main_class()
    {
        if (m_thread.joinable())
            m_thread.join();
    }
 
    void run_connect(std::unique_ptr<Connect> connect)
    {
        m_thread = std::thread(&main::thread_func, this, std::move(connect));
    }
 
protected:
    void thread_func(std::unique_ptr<Connect> connect)
    {
        //Если не выполняется задержка, то здесь некорректный указатель connect
    }
 
    std::thread m_thread;
};
1
0 / 0 / 0
Регистрация: 12.03.2018
Сообщений: 14
03.05.2021, 11:59  [ТС] 7
Спасибо! Неправильно понимал команду join.
Привык в других языках сначала создавать приостановленный поток, а потом его запускать.
C++ не поддерживает такого режима. Поток стартует сразу после создания.
0
49 / 147 / 33
Регистрация: 29.06.2019
Сообщений: 1,428
03.05.2021, 14:31 8
Цитата Сообщение от Icarus7 Посмотреть сообщение
сначала создавать приостановленный поток, а потом его запускать.
но поток же создаёте с действующей в ней функцией?.. иначе смысла не вижу (хотя в др. языках и пустые создают )...
в функции и останавливайте поток на ожидании my_condition_variale.wait()... - смотрите inter-process-communication инструменты...
по вашему вопросу - краткий вариант:
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// https://www.cyberforum.ru/cpp-beginners/thread2823510.html
// Передача указателя в thread 
 
#include <iostream>
#include <bits/stdc++.h>
 
using namespace std;
 
struct Connector{
    int m_id;
    int m_cnt=0;    
    Connector(int i) :m_id(i) {
        m_cnt+=1;
        printf("%d CN created\n", m_cnt); 
        system("pause"); 
    }
    ~Connector(){m_cnt-=1; printf("%d CN left\n", m_cnt);}
};
 
class thrRunner {
private:
    std::atomic<bool> exit_flag; // флаг для синхронизации (опционально)
    std::thread m_thr;
    std::unique_ptr<Connector> m_cn;
 
public:
    // CTOR
     thrRunner(std::unique_ptr<Connector>& c) : exit_flag(false), m_thr (&thrRunner::run_connect,  this), m_cn(move(c))
     {
         // после создания потока не делайте тут ничего, что бросает исключение,
         // поскольку в этом случае не будет вызван деструктор объекта cMyThread,
         // поток не будет завершен, а программа упадет
     }
    // DTOR
     ~thrRunner() {
          exit_flag = true; // говорим потоку остановиться
          m_thr.join();
     }
    // ФУНКЦИЯ ПОТОКА
    void run_connect() {
        while (!exit_flag) {
            // делаем что-нибудь
            printf("t_id %d still connected\n" ,std::this_thread::get_id());
            printf("cn_id from pointer - %d \n" , (*m_cn).m_id);
            this_thread::sleep_for(chrono::seconds(1));
            printf("t_id %d flag changed\n" ,std::this_thread::get_id());
            exit_flag=true;     // ... флаг менять не обязательно здесь, а по логике потока... здесь можно закомментировать
        }
    }
};
 
int main(int argc, const char *argv[])
{
    std::unique_ptr<Connector> ptr = make_unique<Connector>(1); 
    thrRunner t(ptr);
    t.run_connect();
    return 0;
}
можно использовать, как скелет, - я не уверена, что без синхронизации обращения к куче (вашему unique_ptr) этот код полный -- точнее уверена, что обращение к куче в таком коде синхронизировать надо... но я и не уверена, что вы один Connector захотите использовать в разных потоках... поэтому оставляю, как скелет
1
0 / 0 / 0
Регистрация: 12.03.2018
Сообщений: 14
07.05.2021, 11:27  [ТС] 9
Большое спасибо за такие развернутые ответы. Вроде разобрался и с вашей помощью узнал новое)
0
BlackStoneBlack
07.05.2021, 12:33
  #10

Не по теме:

Цитата Сообщение от jugu Посмотреть сообщение
Это кто ж вас учил такие названия классам давать?
Вероятнее всего, Java )00)

0
0 / 0 / 0
Регистрация: 12.03.2018
Сообщений: 14
08.05.2021, 06:39  [ТС] 11
Да. Больше нравится именовать классы с заглавной, а переменные со строчной и разделять слова регистром, а не подчеркиванием.
На некоторых мониторах, когда много подчеркиваний начинается путаница с пробелами.
Пишу для себя, поэтому делаю, чтобы было удобно мне.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
08.05.2021, 06:39
Помогаю со студенческими работами здесь

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

Передача указателя функции
Помогите пожалуйста исправить код а то я в указатели ваще не втыкаю /* Вывести на экран три...

Передача указателя в функцию
Поиском не пользовался, возможно данный вопрос уже проскакивал. Проблема том, что VS2010 на отрез...

Передача указателя на массив
есть arr обьявлен и инициализирован требуется обьявить функцию передать в функцию указатель на...

Передача указателя по ссылке
Так печатается &quot;12&quot; #include &quot;stdafx.h&quot; #include &lt;iostream&gt; using namespace std; void...

Передача указателя функции
Друзья! Need help! Есть пример &quot;Переменный список параметров указателей&quot;. В функции подсчитываем...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru