我有一个正常工作的Visual Studio项目,直到我尝试实现multithreading
。该项目从GigE
相机获取图像,并且在获取10个图像之后,从所获取的图像中制作视频。
程序流程使得程序在制作视频时没有获取图像。我想改变它,所以我创建了另一个从图像中制作视频的线程。我想要的是该程序将连续获取图像,获取10个图像后,另一个并行运行的线程将制作视频。这将持续到我停止程序,获取10张图像,这10幅图像中的视频并行制作,同时获取下10张图像,等等。
我之前没有创建threads
所以我按照this website上的教程进行了操作。与网站类似,我为保存视频的thread
创建了function
。创建视频的function
将10张图片作为vector
参数。我在join
函数终止的行之前的这个线程上执行main
。
为清楚起见,这里是我实施的伪代码:
#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已触发断点。该项目在report_runtime_error.cpp
中的static bool __cdecl issue_debug_notification(wchar_t const* const message) throw()
中断。
我在控制台上打印了一些cout
消息,以帮助我了解正在发生的事情。会发生什么是程序获取10张图像,然后保存视频的thread
开始运行。由于有10个图像,因此必须将10个图像附加到视频中。在第二次获取10张图像后,弹出Project.exe触发断点的消息,此时并行线程仅将第一张获取的图像集中的6张图像附加到视频中。
输出包含多行thread XXXX has exited with code 0
,之后输出显示
Debug Error!
Program: ...Path\Program.exe
abort() has been called
(Press Retry to debug the application)
Program.exe has triggered a breakpoint.
答案 0 :(得分:1)
我无法在评论中解释这一切。我在这里放弃它,因为看起来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
。你可以复制那些。但是你通常不想这样做。问题1:使用相同数据的多个线程?最好只读或防止并发修改。这包括生成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
不断增长。第一个线程,即使被复制,也有十个元素。第二个是前10个加上另外10个。这很奇怪,可能不是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));
这在thread
threads
内emplace_back
创建了thread_method
,images
会使用images
的副本调用std::move
。很有可能编译器会认识到这是$(".div-intro").on('inview', function(event, isInView) {
if (isInView) {
// $(".div").css('visibility','initial');
}else{
console.log("error");
}
});
.div { visibility:hidden;}
这个特定实例的结束并消除了复制,但如果没有,[DllImport("setupapi.dll", SetLastError = true)]
public static extern int CM_Get_Device_ID(uint dnDevInst, StringBuilder Buffer, int BufferLen, int ulFlags = 0);
应该给它提示。
答案 1 :(得分:0)
你是overwriting while循环中的一个线程。如果它仍在运行,程序将中止。您必须加入或分离每个线程值。
你可以改为
#include // ...
#include <thread>
// pass by value, as it's potentially outliving the loop
void thread_method(std::vector<Image> images){
// Save vector of images to video
}
int main(int argc, char* argv[]){
// Some stuff
while(TRUE)
{
std::vector<Image> images; // new vector each time round
for (int i = 0; i < 10; i++)
{
//Acquire Image
//Put image pointer in images vector named images
}
// std::thread::thread will forward this move
std::thread(thread_method, std::move(images)).detach(); // not join
}
// stuff
// this is somewhat of a lie now, we have to wait for the threads too
std::cout << std::endl << "Done! Press Enter to exit..." << std::endl;
std::getchar();
return 0;
}