我的代碼獲取圖像並對其進行處理。性能對我的代碼至關重要,所以我嘗試了多線程。目前,我只是把收購部分作爲一個獨立的線程。我正在使用std::queue
實現一個簡單的FIFO緩衝區,用於存儲獲取的圖像。採集功能AcquireImages
無限期地將原始圖像數據寫入該緩衝區,直到用戶中斷。處理函數,ProcessImages
讀取緩衝區並處理圖像數據(目前在主線程中,但我計劃將其作爲單獨的線程以及一旦我解決了問題)。這裏是我的代碼(改性形成MCV example):如何讀取與另一個線程共享的std :: queue?
#include <iostream>
#include <vector>
#include <queue>
#include <atomic>
#include <thread>
#define NUM_CAMERAS 2
void AcquireImages(std::queue<unsigned char*> &rawImageQueue, std::atomic<bool> &quit)
{
unsigned char* rawImage{};
while (!quit)
{
for (int camera = 0; camera < NUM_CAMERAS; camera++)
{
switch (camera)
{
case 0:
rawImage = (unsigned char*)"Cam0Image";
break;
case 1:
rawImage = (unsigned char*)"Cam1Image";
break;
default:
break;
}
rawImageQueue.push(std::move(rawImage));
}
}
}
int ProcessImages(const std::vector<unsigned char*> &rawImageVec, const int count)
{
// Do something to the raw image vector
if (count > 10)
{
return 1;
}
else
{
return 0;
} // In my application, this function only returns non-zero upon user interception.
}
int main()
{
// Preparation
std::vector<unsigned char*> rawImageVec;
rawImageVec.reserve(NUM_CAMERAS);
std::queue<unsigned char*> rawImageQueue;
int count{};
const unsigned int nThreads = 1; // this might grow later
std::atomic<bool> loopFlags[nThreads];
std::thread threads[nThreads];
// Start threads
for (int i = 0; i < nThreads; i++) {
loopFlags[i] = false;
threads[i] = std::thread(AcquireImages, rawImageQueue, ref(loopFlags[i]));
}
// Process images
while (true)
{
// Process the images
for (int cam{}; cam < NUM_CAMERAS; ++cam)
{
rawImageVec.push_back(rawImageQueue.front());
rawImageQueue.pop();
}
int processResult = ProcessImages(move(rawImageVec), count);
if (processResult)
{
std::cout << "Leaving while loop.\n"; // In my application this is triggered by the user
break;
}
rawImageVec.clear();
++count;
}
// Shutdown other threads
for (auto & flag : loopFlags) {
flag = true;
}
// Wait for threads to actually finish.
for (auto& thread : threads) {
thread.join();
}
return 0;
}
你們有些人可能已經注意到我的失誤。我所知道的是,這個程序在rawImageVec.push_back(rawImageQueue.front());
處拋出異常。
拋出異常後輸出內容如下:
Debug Assertion Failed!
Program: C:\WINDOWS\SYSTEM32\MSVCP140D.dll
File: c:\program files (x86)\microsoft visual studio 14.0\vc\include\deque
Line: 329
Expression: deque iterator not dereferencable
我認識這個問題的原因可能是,我正在讀與另一個線程共享的東西(對嗎?)。我該如何解決這個問題?
我跟着Praetorian的建議在評論後,檢查rawImageQueue
是否爲空,我發現它總是空的。我不確定是什麼原因造成的。
用互斥體或類似的方法保護隊列。 –
在調用'rawImageQueue.front()'之前,您沒有檢查隊列是否爲空。並且從任一線程進入隊列的所有訪問必須受互斥體保護。 – Praetorian
閱讀有關「生產者消費者模式」(例如https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem),解決當前問題後首先要考慮的問題 - 當生產者生產速度更快時會發生什麼比消費者消費 –