Почему создание потока в конструкторе приводит к ошибке во время выполнения - PullRequest
0 голосов
/ 03 сентября 2018

У меня следующий код на C ++, я пытаюсь создать новый поток из конструктора класса. Я получаю ошибку во время выполнения. Я не понимаю, почему и как это можно предотвратить. Я довольно новичок в C ++. В VS2017 он вызывал ошибки в abort ().

#include <iostream>
#include <thread>
#include <chrono>

class Rectangle {
public:
    int area(void);
    Rectangle();
    ~Rectangle();

private:
    int x, y;
    int UpdateData();
};

Rectangle::Rectangle() {
    x = 1;
    y = 2;
    std::thread modelThread(&Rectangle::UpdateData, this);
}

Rectangle::~Rectangle() {
}
int Rectangle::area() {
    return x * y;
}
int Rectangle::UpdateData()
{
    while (true) {
        x++;
        y += 2;
        std::cout << "Area with x:" << x << " y:" << y << " area:" << Rectangle::area() << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(2000));
    }
    return 0;
}

int main() {
    Rectangle rect;
    return 0;
}

1 Ответ

0 голосов
/ 04 сентября 2018

main и modelThread являются потоками, но modelThread запускается из main через конструктор Rectangle. Однако, когда main заканчивается, rect выходит из области видимости и уничтожается, в то время как поток, запущенный в его конструкторе, все еще работает. Это вызывает ошибку во время выполнения. Поэтому вам нужно присоединить поток modelThread к потоку main, чтобы убедиться, что основное устройство ожидает завершения работы modelThread.

Но сейчас я не могу выполнить код в основной функции. Как я могу достичь обоих

Для этого вам нужно будет сделать UpdateData public и запустить modelThread в основном так:

std::thread modelThread(&Rectangle::UpdateData, &rect);

Даже с std::async вам придется сделать UpdateData public и использовать его так:

std::future<int> fut =  std::async (&Rectangle::UpdateData, &rect);

Если вы не хотите, чтобы сделал UpdateData public, объявите функцию friend в классе Rectangle (которая может получить доступ ко всем ее закрытым членам и функциям) и вызовите UpdateData в friend и запустите поток в main с помощью этой функции friend.

std::future<int> fut =  std::async (&FriendFunc, &rect);

Тогда вы сможете выполнить код в main, не дожидаясь завершения UpdateData. Затем вы можете получить значение, вычисленное функцией UpdateData, используя следующее в main.

int ret = fut.get();      

Если вы хотите, чтобы выходы из main и UpdateData не были перепутаны, сделайте это.
Объявите переменную-член private в Rectangle

std::mutex mtx; //uses <mutex>

И используйте это так:

int Rectangle::UpdateData()
{
    std::lock_guard<std::mutex> lock(mtx);
    while (true) {
        x++;
        y += 2;
        std::cout << "Area with x:" << x << " y:" << y << " area:" << Rectangle::area() << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(2000));
    }
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...