質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

解決済

2回答

10627閲覧

マルチスレッドによるWindows Formでのイベント発生によるエラー

NaiveBlaziken

総合スコア7

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

1グッド

0クリップ

投稿2016/10/17 11:14

###前提・実現したいこと
VisualStudioでOpenCVを用いて、動画の各フレーム対して画像処理を行い、その結果を表示するwindowsフォームアプリケーションを作成しようとしています。
画像処理部をマルチスレッドにて実装したのですが、デバッグ中にフォームの位置を動かそうとした際に以下の問題が発生しました。

###発生している問題・エラーメッセージ

型 'System.AccessViolationException' の例外が System.Drawing.dll で発生しましたが、ユーザー コード内ではハンドルされませんでした 追加情報: 保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。 この例外のハンドラーがある場合は、プログラムを安全に続行できます。

そのまま無理やりデバックを続行させるとFormのShowDialog()で

型 'System.Reflection.TargetInvocationException' のハンドルされていない例外が mscorlib.dll で発生しました 追加情報: 呼び出しのターゲットが例外をスローしました。

が出力されます

###該当のソースコード

C++

1//メインスレッド 2 private: System::Void button3_Click(System::Object^ sender, System::EventArgs^ e) { 3 button3->Enabled = false; 4 Thread^ t = gcnew Thread(gcnew ThreadStart(this, &MyForm::ImageProc)); 5 t->IsBackground = true; 6 t->Start(); 7 } 8//サブスレッド 9 private: System::Void ImageProc(){ 10 cv::Mat image; 11 cv::VideoCapture cap("movie.avi"); 12 if (!cap.isOpened()) { 13 return; 14 } 15 while (true){ 16 cap >> image; 17 if (image.empty()) { 18 break; 19 } 20 21 cvtColor(img, img, CV_BGR2GRAY); 22 23 /* 24 実際の処理 25 */ 26 27 cvtColor(img, img, CV_GRAY2BGR); 28 29 IntPtr ip(imgBGR.ptr()); //Mat画像バッファをintポインタに変換 30 Bitmap^ bmp; 31 bmp = gcnew Bitmap(image.cols, image.rows, image.step, System::Drawing::Imaging::PixelFormat::Format24bppRgb, ip); 32 33 BeginInvoke( 34 gcnew updateImageDelegate(this, &MyForm::UpdateImage), 35 bmp, image.cols, image.rows); 36 Sleep(10); 37 } 38 } 39 40 private: delegate System::Void updateImageDelegate(Bitmap^ bmp, int cols, int rows); 41 //画像の更新 42 private: System::Void UpdateImage(Bitmap^ bmp, int cols, int rows){ 43 Graphics^ gp = pictureBox1->CreateGraphics(); //グラフィックオブジェクト作成 44 gp->DrawImage(bmp, 0, 0, cols / 2, rows / 2); 45 //delete gp; 46 } 47

###確認していること

問題が発生した際の現在の関数は gp->DrawImage(bmp, 0, 0, cols / 2, rows / 2);

問題が発生するのはフォーム移動、最小化、ボタン操作、他のボタン操作により作成されたウィンドウを閉じる操作

上記操作をしても問題が発生するタイミングとしないタイミングがある

UpdateImageを

private: System::Void UpdateImage(Bitmap^ bmp, int cols, int rows){ Graphics^ gp = pictureBox1->CreateGraphics(); //グラフィックオブジェクト作成 gp->DrawImage(bmp, 0, 0, cols / 2, rows / 2); Sleep(100); }

に書き換えると2~3フレーム目でフォーム操作をしなくても問題が発生。Sleep(10)だと発生しないが、Sleepさせない時よりフォーム操作等により問題が発生する確率は上がっていると感じた。

以上からgp->DrawImageを実行中にイベントを引き起こすと発生するようなのですが、どのように変更したら良いのかわかりません。ご教授お願い致します。

###補足情報(言語/FW/ツール等のバージョンなど)
Microsoft Visual Studio Express 2013 for Windows Desktop
OpenCV 2.4.13

episteme👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

こんにちは。

BeginInvoke()は非同期で要求を発行するため、次々とupdateImageDelegateが要求され、メイン・スレッドの処理が追いつかなくなって異常動作しているのではないでしょうか?
BeginImvoke()ではなくInvoke()を使ってメイン・スレッドの処理完了を待てばよいように思います。

投稿2016/10/17 13:41

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

NaiveBlaziken

2016/10/18 02:18

ありがとうございます。解決いたしました。 同期非同期の認識が足りていませんでした。
guest

0

別スレッドからフォームやコントロールを操作する場合は、deleagate を使用し Invoke などで処理しないと Refrection で例外が発生します。

参考URL

投稿2016/10/17 11:27

mugicya

総合スコア1046

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問