私は経験しましたこのSOの質問しかしそれは役に立ちませんでした。
ここでのケースは異なります。私はバックグラウンドワーカーを使用しています。1番目のバックグラウンドワーカーはユーザーの画像入力で動作を開始し、firstbackgroundworker_runworkercompleted()内で他の3つのバックグラウンドワーカーを呼び出しています。
algo1backgroundworker.RunWorkerAsync();
algo2backgroundworker.RunWorkerAsync();
algo3backgroundworker.RunWorkerAsync();
それぞれのコードは次のとおりです。
algo1backgroundworker_DoWork()
{
Image img = this.picturebox.Image;
imgclone = img.clone();
//operate on imgclone and output it
}
algo2backgroundworker_DoWork()
{
Image img = this.picturebox.Image;
imgclone = img.clone();
//operate on imgclone and output it
}
同様の操作が他の algo*backgrougrondworker_doWork() でも実行されます。
時々、「InvalidOperationException - オブジェクトは現在他の場所で使用されています」というエラーが発生します。これは非常にランダムです。algo1backgroundworker_DoWork で時々発生し、algo2backgroundworker_DoWork でも時々発生し、Application.Run(new myWindowsForm()); でも時々発生します。
何が起こっているのか全く分かりません。
ベストアンサー1
GDI+ には、2 つのスレッドが同時にビットマップにアクセスするのを防ぐロックがあります。これはブロックするタイプのロックではなく、「プログラマーが何か間違ったことをしたので、例外をスローする」タイプのロックです。スレッドがクラッシュするのは、すべてのスレッドでイメージを複製している (== ビットマップにアクセスしている) ためです。UI スレッドがクラッシュするのは、スレッドがビットマップを複製しているのと同時に、UI スレッドがビットマップを描画しようとしている (== ビットマップにアクセスしている) ためです。
ビットマップへのアクセスを 1 つのスレッドのみに制限する必要があります。BGW を開始する前に UI スレッドでイメージを複製します。各 BGW にはイメージの独自のコピーが必要です。RunWorkerCompleted イベントで PB の Image プロパティを更新します。この方法では同時実行性が多少失われますが、これは避けられません。