- 問題の説明
- 工程1:カメラから画像データを取得し、その後CV ::マットオブジェクト(オブジェクトがデータを交換するために、グローバル変数)に格納されています。カメラが自動的にコールバック関数によって呼び出されます。
- 工程2:上記グローバル変数のコピーとqimg変換、Qtは、表示画面上に配置されました。このプロセスは、タイマーによって呼び出されます。
- その後、プログラムはいくつかの時間のために実行され、「プログラムが異常【選択プロセスが強制的に終了したに終了します。」。期間を変化させて実行されます。
- 問題解決と分析
- QtCreatorコンパイラオプションはMSVCであるが、唯一のデバッガGDB(次のCDBを必要としているようだチェック)選択したため。これは、調査の少しだけデバッグすることは不可能です。
- テストタイマー短い時間、迅速な問題。アクセス違反の推測では、マルチスレッドです。
- スレッドIDを表示する出力、使用のstd :: this_thread :: GET_ID()は、現在のスレッドのIDを取得し、オブジェクトがマットマットスレッド番号書き込ま手順オブジェクトカメラスレッド番号を読み、タイマーが同じではない呼び出しが見つかりました。これは、画像データのSDKセクションのカメラの新しいスレッドを作成することであることを示しています。
- しかし、読者は競合いけないので、OpenCVのマット:: clone()メソッドを見てみましょう。
inline Mat Mat::clone() const { Mat m; copyTo(m); return m; } // 噢 原来是调用的cv::copyTo方法,等等,上面有个const,这下明白了,在拷贝的时候是不允许修改值的,如果正在拷贝,此时相机写入线程正好获取了相机数据,准备写入,这时就发生了冲突。总之读写不能同时进行。 //那么就是用互斥量将两者互斥, #include <mutex> std::mutex mtx; //在读(Mat::clone()) / 写 之前使用mtx.lock();,之后使用mtx.unlock(); 问题解决啦。
- 最後に、これは本当に理由であるかどうかをテストします。スロット機能、クリックボタンの接続操作を宣言します。.clone呼び出し()とロックされていません。
void QtGuiApplication1::on_btnThread_clicked()
{
auto myThread = [] {
while (1) {
if (!temp_forSave.empty()) {
Mat lalala = temp_forSave.clone();
std::cout << "在创建线程中复制\n";
}
std::cout << "创建线程" << std::this_thread::get_id() << "运行" << endl;
}
};
std::thread a(myThread);
a.join();
}
- (スレッドは(1)コピーするときながら、結局)通常動作時には、ボタンをクリックして、プログラムがすぐにクラッシュします。検証が成功しています。