[英]how to convert to "C" format by using std::bind member function of a class as a thread portal function?
[英]Start thread within member function using std::thread & std::bind
我對下面的代碼快照幾乎沒有疑問。
1) 關於 pthread_create(),假設 Thread_1 創建 Thread_2。 據我了解,Thread_1 可以在不加入的情況下退出,但 Thread_2 仍將繼續運行。 在下面沒有 join() 的示例中,我無法運行線程並且我看到異常。
2)在幾個例子中,我看到沒有線程 object 的線程創建如下。 但是當我這樣做時,代碼被終止。
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);
語句創建和銷毀線程 object。 std::thread
的析構函數在線程未加入或分離時調用std::terminate
(就像在您的語句中一樣)。
沒有充分的理由在 C++11 中使用std::bind
,因為 lambda 在空間和速度方面更好。
在構建多線程代碼時,您需要在編譯和鏈接時指定-pthread
選項。 Linker 選項-lpthread
既不充分又不必要。
根據設計,您需要加入您生成的所有線程,或將它們分離。 請參閱例如關於加入/分離的 SO 問題
另請參閱cppreference,分離
如果 main() 在分離的線程仍在運行時退出,還要注意重要的警告
我也 100% 同意另一個答案中關於更喜歡綁定 lambda 的評論。
最后,不要陷入在 C++ 中的線程上執行 pthread_cancel 的誘惑。 參見例如pthread_cancel 被認為是有害的
在 C++ 中,對象具有生命周期。 這與處理 C 中的句柄有點不同。 在 C++ 中,如果您在一個 scope 中的堆棧上創建 object,則如果退出 Z31A1FD140BE4BEF2D8ZA11E,它將被銷毀。 這些規則有一些例外,例如std::move
,但根據經驗,您擁有 object 的生命周期。
這與上述相同的答案有關。 當你調用std::thread(&Task::executeThread, this);
您實際上是在調用線程構造函數。 這是線程生命周期和 object 生命周期的開始。 請注意,您在堆棧上創建了此 object。 如果您離開 scope {.. yourcode.. }
將調用 DTor。 由於您在std::move
、 join
或detatch
之前完成了此操作,因此調用std::terminate()
會引發異常。
相關文檔:
我個人建議了解 C++ 中對象的生命周期。 簡而言之,所有對象的生命周期都是在調用其構造函數時開始的。 當它們被殺死(如超出范圍)時,它們的析構函數被調用。 編譯器會為您處理此問題,因此如果您來自 C,它是一個新概念。
謝謝大家的意見。 作為線程創建的一部分,我錯過了線程 object。 因為這個雖然編譯,我得到了例外。 下面是我更新的代碼。 所有三種情況都運行良好。
#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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.