为什么在构造函数中创建线程会导致运行时错误

时间:2018-09-03 17:02:27

标签: multithreading c++11

我在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 :(得分:2)

mainmodelThread是线程,但是modelThread是通过main的构造函数从Rectangle启动的。但是,当main结束时,rect超出范围并被破坏,而在其构造函数中启动的线程仍在运行。这会导致运行时错误。 因此,您必须将modelThread加入main线程中,以确保主线程一直等到modelThread完成运行。

  

但是现在,我无法在main函数中执行代码。我怎样才能做到

为此,您必须制作UpdateData public并像这样在main中启动modelThread

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

即使使用std::async,您也必须制作UpdateData public并像这样使用它:

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

如果您不想制作UpdateData public,请在Rectangle类中声明一个friend函数(可以访问其所有私有成员和函数)并在UpdateData函数中调用friend,并使用该main函数在friend中启动线程。

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

然后,您将可以在main中执行代码,而无需等待UpdateData完成。然后,您可以使用UpdateData中的以下内容来获取由main函数计算出的值。

int ret = fut.get();      

如果您不想混用mainUpdateData的输出,请执行此操作。
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;
}