线程已退出,代码为 1:Join() 和 Detach()
The thread has exited with code 1: Join() and Detach()
我开发了一个软件,需要下载多个图像并使用opencv进行一些处理。我正在使用 curllib 下载图像。所以基本上我从不同的网络摄像机获取图像。我想做的是同时下载这些图像,所以我尝试使用detach()
并调用 curllib。我尝试使用detach()
的主要原因是不要等待可能需要更长时间或超时的下载。所以我想处理主循环中可用的内容。当我使用detach()
时,程序停止而没有任何错误或显示:
The thread .... has exited with code 1
The thread ....has exited with code 1
之后:
The program.... has exited with code 1....
没有例外,没有错误,什么都没有。 只是它。
如果我改成join()
它永远不会停止。但是通过加入,我需要等待所有线程下载所有图像或超时。
我将展示一个包含两个申请的示例:
//create class
ProcessImage* camera1 = new ProcessImage;
ProcessImage* camera2 = new ProcessImage;
for (;;) {
/* Must initialize libcurl before any threads are started */
curl_global_init(CURL_GLOBAL_ALL);
// Load Image into Class variable
std::thread th(&ProcessImage::loadimage, camera1);
if (th.joinable()) {
th.detach();
}
std::thread th2(&ProcessImage::loadimage, camera2);
if (th2.joinable()) {
th2.detach();
}
// Process with Opencv
camera1->run();
camera2->run();
}
我的加载图像功能:
void ProcessImage::loadimage() {
Mat loading;
//insert user and password
string password = ConfigData.username + ":" + ConfigData.password;
// Loading image with Curl
loading = curlImgClass(ConfigData.urlSnapshot.c_str(), password.c_str(), 5);
lastfail = false;
// Internal variable to store the downloaded image
img = loading.clone();
if (loading.empty()) {
lastfail = true;
endoperation = true;
}
if (loading.total() < 500) {
lastfail = true;
endoperation = true;
}
}
卷曲功能:
size_t ProcessImage::write_dataClass(char *ptr, size_t size, size_t nmemb, void *userdata)
{
vector<uchar> *stream = (vector<uchar>*)userdata;
size_t count = size * nmemb;
stream->insert(stream->end(), ptr, ptr + count);
return count;
}
cv::Mat ProcessImage::curlImgClass(const char *img_url, string userpass, int timeout)
{
vector<uchar> stream;
CURL *curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, img_url); //the img url
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); // pass the writefunction
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &stream); // pass the stream ptr to the writefunction
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5); // timeout if curl_easy hangs,
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
if (userpass != ":") {
const char * c = userpass.c_str();
curl_easy_setopt(curl, CURLOPT_USERPWD, c);
}
CURLcode res = curl_easy_perform(curl); // start curl
curl_easy_cleanup(curl); // cleanup
/* Check for errors */
if (res != CURLE_OK) {
//return imdecode(stream, -1); // 'keep-as-is'
cv::Mat test(cv::Size(1, 1), CV_64FC1);
return test; // 'keep-as-is'
}
else {
return imdecode(stream, -1);
}
}
我该怎么做才能让它与detach()
一起工作? 我尝试了很多像std::lock_guard<std::mutex>
这样的控件,但没有任何效果,软件不断退出。
编辑:我在两个函数中使用的唯一变量是img
:
int ProcessImage::run(){
if ( (img.total() < 500) || (lastfail == true)) {
failcount = failcount + 1;
// create a black window
Mat imagefail(480, 640, CV_8UC3, Scalar(0, 0, 0));
// putText(imagefail, "Connection Fail", cvPoint(480 / 2, 480 / 2), CV_FONT_HERSHEY_COMPLEX_SMALL, 1, CV_RGB(255, 255, 255), 1, 8, false);
imshow(ConfigData.name.c_str(), imagefail);
waitKey(20);
m_lock2 = false;
std::cout << "connection fail n";
return -1; // load fail
//}
}
else {
failcount = 0;
}
Mat sendimage = img.clone();
Mat opacity = sendimage.clone();
//// do other stuff with sendimage now ////
}
您的代码具有未定义的行为。loadimage
填充img
,run
从img
读取,而无需任何同步。 这个凸轮会导致各种问题,其中之一是您当前观察到的问题。 要解决此问题,您需要使用某种同步来确保在写入时不会读取。 最简单的方法是将loadimage
和run
移动到单个线程中。 这样,它们将按对象连续运行,因此您没有机会进行数据竞赛。 这会将您的 for 循环更改为如下所示
//create class
ProcessImage* camera1 = new ProcessImage;
ProcessImage* camera2 = new ProcessImage;
for (;;) {
/* Must initialize libcurl before any threads are started */
curl_global_init(CURL_GLOBAL_ALL);
// Load Image into Class variable and process
std::thread th([](){ camera1->loadimage(); camera1->run(); });
std::thread th2([](){ camera2->loadimage(); camera2->run(); });
// join or detach threads, if wanting to detach consider using a thread pool or adding threads to a container instead
th.join(); // possibly detach
th2.join(); // possibly detach
}
我在代码中使用了join
,但如果您不想等待,可能需要detach
。 也就是说,您可以通过将线程存储在容器中来解决此问题,然后在程序退出之前调用所有线程上的 join 以确保在应用程序终止之前完成所有操作。 您也可以为此利用线程池。
- 在std::thread中,joinable()然后join()线程安全吗
- join() 失败,如果在线程内部调用 io_context.run()
- std::future::get()或std::future::wait()是std::thread::join()的替
- c++17 std::thread join() : 没有这样的进程
- std::thread::join() 可以从非父线程调用吗?
- 使用 vector<thread> 和 .join() 未并行运行的多线程C++程序
- 为什么在线程销毁之前必须调用 join() 或 detach()
- 线程在销毁包含该线程的对象时调用 thread.detach()
- thread.join() 的工作原理
- 有没有办法在C++中实现 Python 的 join()?
- 使用Boost :: Join合并多个阵列
- 寻找 std::join 行为的澄清
- thread.detach() 函数的左值何时会超出以下代码的范围
- 使用 Ranges-v3 视图::join保留双向性
- 当调用std :: thread.detach时出乎意料的行为
- 在我调用join()之前,std ::线程运行
- 线程:join上是否存在具有synchronized with relationship的隐式内存障碍
- 线程已退出,代码为 1:Join() 和 Detach()
- 关于了解C++线程"detach()"的问题
- 线程上的"detach()"有什么作用?.CPP