- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在我尝试实现多线程
之前,我有一个 Visual Studio 项目运行良好。该项目从 GigE
相机获取图像,在获取 10 张图像后,根据获取的图像制作视频。
程序流程是这样的,程序在制作视频时没有获取图像。我想改变这一点,所以我创建了另一个线程,从图像制作视频。我想要的是该程序将连续获取图像,在获取 10 张图像后,另一个线程并行运行以制作视频。这将一直持续到我停止程序,获取 10 张图像,同时获取这 10 张图像的视频,同时获取下 10 张图像,依此类推。
我之前没有创建过threads
,所以我遵循了this website 上的教程.和网站类似,我为保存视频的函数
创建了一个thread
。创建视频的 function
将 10 张图像作为 vector
参数。我在 main
函数终止的行之前在此线程上执行 join
。
为清楚起见,这是我实现的伪代码:
#include ...
#include <thread>
using namespace std;
thread threads[1];
vector<Image> images;
void thread_method(vector<Image> & images){
// Save vector of images to video
// Clear the vector of images
}
int main(int argc, char* argv[]){
// Some stuff
while(TRUE)
{
for (int i = 0; i < 10; i++)
{
//Acquire Image
//Put image pointer in images vector named images
}
threads[0] = thread(thread_method, images)
}
// stuff
threads[0].join();
cout << endl << "Done! Press Enter to exit..." << endl;
getchar();
return 0;
}
当我现在运行项目时,弹出一条消息说 Project.exe 已触发断点。该项目在 static bool __cdecl issue_debug_notification(wchar_t const* const message) throw()
中的 report_runtime_error.cpp
中中断。
我正在控制台上打印一些 cout
消息以帮助我了解正在发生的事情。发生的情况是程序获取了 10 张图像,然后用于保存视频的 thread
开始运行。由于有 10 张图像,因此必须将 10 张图像附加到视频中。第二次获取10张图片后弹出Project.exe已触发断点的消息,此时并行线程仅将第一次获取的一组图片中的6张图像附加到视频中。
输出包含多行thread XXXX has exited with code 0
,之后输出为
调试错误!
程序:...Path\Program.exe
abort() 已被调用
(按重试调试应用程序)
Program.exe 已触发断点。
最佳答案
我无法在评论中解释所有这些。我把它放在这里是因为看起来 OP 正朝着一些不好的方向前进,我想在悬崖前阻止他。 Caleth 捕获了大爆炸并提供了避免大爆炸的解决方案,但大爆炸只是 OP 的一个症状,使用 detach
的解决方案有些问题。
using namespace std;
Why is "using namespace std" considered bad practice?
thread threads[1];
数组 1 几乎毫无意义。如果我们不知道会有多少个线程,请使用 vector
。另外,没有充分的理由将其作为全局变量。
vector<Image> images;
同样,没有充分的理由让它成为全局性的,但有很多理由不成为全局性的。
void thread_method(vector<Image> & images){
通过引用传递可以为您节省一些复制,但是 A) 您不能复制引用并且线程会复制参数。好的,所以使用指针或 std::ref
。你可以复制那些。但你通常不想这样做。问题一:多个线程使用同一份数据?最好是只读的或防止并发修改。这包括生成 vector
的线程。 2. 引用仍然有效吗?
// Save vector of images to video
// Clear the vector of images
}
int main(int argc, char* argv[]){
// Some stuff
while(TRUE)
{
for (int i = 0; i < 10; i++)
{
//Acquire Image
//Put image pointer in images vector named images
}
threads[0] = thread(thread_method, images)
因为 Caleth 提到的原因而变得糟糕。另外 images
不断增长。第一个线程,即使被复制,也有十个元素。第二个有前十个加上另一个十个。这很奇怪,可能不是 OP 想要的。对此 vector
的引用或指针是致命的。 vector
将在其他线程使用它时调整大小,从而使旧数据存储区失效并使其无法安全迭代。
}
// stuff
threads[0].join();
错误的原因由 Caleth 涵盖
cout << endl << "Done! Press Enter to exit..." << endl;
getchar();
return 0;
}
加入线程的解决方案与几乎所有未解决为“使用 std::string
”的 Stack Overflow 问题相同:使用 std::vector
。
#include <iostream>
#include <vector>
#include <thread>
void thread_method(std::vector<int> images){
std::cout << images[0] << '\n'; // output something so we can see work being done.
// we may or may not see all of the numbers in order depending on how
// the threads are scheduled.
}
int main() // not using arguments, leave them out.
{
int count = 0; // just to have something to show
// no need for threads to be global.
std::vector<std::thread> threads; // using vector so we can store multiple threads
// Some stuff
while(count < 10) // better-defined terminating condition for testing purposes
{
// every thread gets its own vector. No chance of collisions or duplicated
// effort
std::vector<int> images; // don't have Image, so stubbing it out with int
for (int i = 0; i < 10; i++)
{
images.push_back(count);
}
// create and store thread.
threads.emplace_back(thread_method,std::move(images));
count ++;
}
// stuff
for (std::thread &temp: threads) // wait for all threads to exit
{
temp.join();
}
// std::endl is expensive. It's a linefeed and s stream flush, so save it for
// when you really need to get a message out immediately
std::cout << "\nDone! Press Enter to exit..." << std::endl;
char temp;
std::cin >>temp; // sticking with standard librarly all the way through
return 0;
}
为了更好的解释
threads.emplace_back(thread_method,std::move(images));
这在 threads
(emplace_back
) 中创建了一个 thread
,它将使用 的拷贝调用
。很有可能编译器会认识到这是 thread_method
>图像images
的这个特定实例的终点并消除了复制,但如果没有,std::move
应该给它提示。
关于c++ - "Project.exe has triggered a breakpoint"实现多线程后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45360815/
我是一名优秀的程序员,十分优秀!