Запустить поток внутри функции-члена, используя std :: thread & std :: bind - PullRequest
0 голосов
/ 07 октября 2019

У меня мало запросов относительно приведенного ниже снимка кода.

1) Что касается pthread_create (), предположим, что Thread_1 создает Thread_2. Насколько я понимаю Thread_1 может выйти без объединения, но все же Thread_2 продолжит работу. Где, как в примере ниже без join (), я не могу запустить поток, и я вижу исключения.

2) В нескольких примерах я вижу создание потока без объекта потока, как показано ниже. Но когда я делаю то же самое, код прекращается.

std::thread(&Task::executeThread, this);

I am compiling with below command.
g++ filename.cpp -std=c++11 -lpthread

Но все равно он завершается за исключением. Это правильный способ создания потока или есть какая-то другая версия C ++ (В моем проекте они уже компилируются, но не уверены в версии).

3) В нескольких примерах кода моего проекта я вижуниже способ создания темы. Но я не могу выполнить приведенный ниже пример.

std::thread( std::bind(&Task::executeThread, this) );

Ниже приведен мой снимок кода.

#include <iostream>
#include <thread>

class Task
{
    public:
    void executeThread(void)
    {
        for(int i = 0; i < 5; i++)
        {
           std::cout << " :: " << i << std::endl;
        }
    }

    void startThread(void);
};

void Task::startThread(void)
{
    std::cout << "\nthis: " << this << std::endl;

#if 1
    std::thread th(&Task::executeThread, this);
    th.join(); // Without this join() or while(1) loop, thread will terminate
    //while(1);
#elif 0
    std::thread(&Task::executeThread, this);  // Thread creation without thread object
#else
    std::thread( std::bind(&Task::executeThread, this) );
    while(1);
#endif
}

int main()
{
    Task* taskPtr = new Task();
    std::cout << "\ntaskPtr: " << taskPtr << std::endl;

    taskPtr->startThread();

    delete taskPtr;
    return 0;
}

Спасибо и С уважением

Вишну Бима

Ответы [ 4 ]

5 голосов
/ 07 октября 2019

std::thread(&Task::executeThread, this); оператор создает и уничтожает объект потока. Деструктор из std::thread вызывает std::terminate, когда поток не был присоединен или отсоединен (как в вашем утверждении).

Нет веской причины использовать std::bind в C++ 11, потому что лямбды лучше с точки зрения пространства и скорости.

При сборке многопоточного кода необходимо указать параметр -pthread при компиляции и компоновке. Опция компоновщика -lpthread неадекватна и не нужна.

4 голосов
/ 07 октября 2019

По замыслу вам нужно присоединиться ко всем темам, которые вы создали, или отсоединить их. См., Например, SO вопрос о присоединении / отсоединении

См. Также cppreference, detach

Обратите внимание также на важные предостережения , если main () завершается, покаотдельные потоки все еще работают

Я также на 100% согласен с комментарием в другом ответе о предпочтении связывания лямбд.

Наконец, не поддавайтесь искушению сделать pthread_cancelпоток в C ++. См. Например pthread_cancel, считающийся вредным

1 голос
/ 07 октября 2019
  1. В C ++ объекты имеют время жизни. Это немного отличается от работы с дескрипторами в C. В C ++, если вы создаете объект в стеке в одной области видимости, он будет уничтожен при выходе из этой области. Есть некоторые исключения из этого правила, такие как std::move, но, как правило, вы владеете временем жизни объекта.

  2. Это связано с тем же ответом, что и выше. Когда вы вызывали std::thread(&Task::executeThread, this);, вы фактически вызывали конструктор потока. Это начало жизни потока и времени жизни объекта. Обратите внимание, что вы создали этот объект в стеке. Если вы покинете область действия { .. yourcode .. }, будет вызван DTor. Поскольку вы сделали это до std::move, join или detatch, то вызывается std::terminate(), что вызывает исключение.

  3. Таким способом вы можете создать тему. Если вы посмотрите на связанную документацию для std :: thread :: thread (constructor), то есть пример того, как объект foo создается таким же образом. Какие ошибки вы получаете?

Соответствующая документация:

a. std :: thread :: ~ thread ()

b. std :: thread :: thread

c. Время жизни в C ++

Я лично рекомендовал бы понять время жизни объектов в C ++. Короче говоря, все объекты начинают свою жизнь, когда вызывается их конструктор. Когда они убиты (как вне области видимости), их деструктор вызывается. Компилятор обрабатывает это для вас, поэтому, если вы пришли из C, это новая концепция.

0 голосов
/ 08 октября 2019

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

#include <iostream>
#include <thread>

class Task
{
    public:
    void executeThread(std::string command)
    {
        for(int i = 0; i < 5; i++)
        {
            std::cout << command << " :: " << i << std::endl;
        }
    }

    void startThread(void);
    std::thread th2;
    std::thread th3;
};

void Task::startThread(void)
{
    std::cout << "\nthis: " << this << std::endl;

    #if 0
        std::thread th1(&Task::executeThread, this, "Thread1");
        th1.join(); // Without join(), thread will terminate
    #elif 0
        th2 = std::thread(&Task::executeThread, this, "Thread2");
        th2.join();
    #else
        th3 = std::thread( std::bind(&Task::executeThread, this, "Thread3") );
        th3.join();
    #endif
}

int main()
{
    Task* taskPtr = new Task();
    std::cout << "\ntaskPtr: " << taskPtr << std::endl;

    taskPtr->startThread();

    delete taskPtr;
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...