使用 std::thread & std::bind 在成员函数中启动线程
Start thread within member function using std::thread & std::bind
我对下面的代码快照几乎没有疑问。
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;
}
感谢和问候
毗湿奴比玛
std::thread(&Task::executeThread, this);
语句创建并销毁线程对象。std::thread
的析构函数在线程未连接或分离时调用std::terminate
(如在语句中(。
没有充分的理由在 C++11 中使用std::bind
,因为 lambda 在空间和速度方面更好。
构建多线程代码时,需要在编译和链接时指定-pthread
选项。链接器选项-lpthread
既不充分又不必要。
根据设计,您需要连接您生成的所有线程,或分离它们。例如,请参阅有关连接/分离的 SO 问题
另请参阅 cpp首选项,分离
另请注意,如果 main(( 在分离的线程仍在运行时退出,则需注意重要的注意事项
我也 100% 同意另一个答案中关于更喜欢 lambda 绑定的评论。
最后,不要陷入在C++线程上做pthread_cancel的诱惑。例如,pthread_cancel被认为是有害
的-
在C++对象有生存期。这与在 C 中处理句柄有点不同。C++,如果您在一个作用域的堆栈上创建一个对象,则退出该作用域时该对象将被销毁。这些规则有一些例外,如
std::move
,但根据经验,您拥有对象的生命周期。 -
这与上述答案相同。当您调用
std::thread(&Task::executeThread, this);
时,您实际上是在调用线程构造函数。这是线程寿命和对象生存期的开始。请注意,您在堆栈上创建了此对象。如果将作用域{ .. yourcode .. }
将调用 DTor。由于您在std::move
、join
或detatch
之前已经这样做了,因此调用std::terminate()
引发异常。 - 您可以通过这种方式创建线程。如果您查看 std::thread::thread(构造函数(的链接文档,就会发现一个以相同方式创建对象 foo 的示例。您收到哪些错误?
相关文档:
a. std::thread::~thread((
b. 标准::线程::线程
c. C++寿命
我个人建议了解C++中对象的生存期。简而言之,所有对象在调用其构造函数时开始其生存期。当它们被杀死时(如在范围之外(,它们的析构函数被调用。编译器会为您处理此问题,因此,如果您来自 C,这是一个新概念。
谢谢大家的投入。我错过了线程对象作为线程创建的一部分。因此,虽然编译,但我得到了例外。下面是我更新的代码。所有三种方案都工作正常。
#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;
}
- 使用std::函数映射对象方法
- 可组合的lambda/std::函数与std::可选
- 当使用透明的std函数对象时,我们还需要写空的尖括号吗
- std::函数常量正确性未遵循
- 具有变量Number of Arguments的std::函数的矢量
- 从类型std::函数传递变量失败,尽管调用方期望的类型完全相同
- 如何调用存储在指向"std::函数"的指针中的 lambda?
- C++ STD 函数运算符:有没有一种方法可以通过函数将一个向量映射到另一个向量上?
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 如何将类 1 的 std::函数绑定到类 2 的函数?
- 如何制作可以接受任何类型的参数的 std::函数和 lambda
- 如何将 STL 队列推送函数绑定到 std::函数?
- std::函数不起作用,但普通的旧函数指针可以 - 为什么?
- 获取 std::函数以推断按引用传递/按值传递
- std::bind 和 std::函数术语不值为接受 0 个参数?
- 从其存储的回调中删除 std::函数是否安全
- 创建 std::函数,它返回具有函数成员值的变量.分段错误
- 创建一个带有 lambda 的 std::函数,而不知道函数的参数
- std::函数的解释
- 在调用过程中删除 std::函数