Visual Studio を使用して、Visual C# を初めて使用します。並列 for ループで実行されるいくつかの計算があり、このループ内の出力テキスト ボックスに何かを出力したいと考えています (画面上の計算からのすべての出力を保持します)。テキストボックスにテキストを追加できるようにしたいだけです(または、すでにあるものにテキストを追加したいだけです)。
Windowsフォームへのスレッドセーフ呼び出しに関する次のリンクを見つけました。彼らは、提示されたケースで両方とも機能する2つの例を示しています。テキストボックスにメッセージを表示しているだけです。テキストボックスにデータを追加したい。次のコード (最初の方法) を動作させることができます。
private void setTextSafeBtn_Click(object sender, EventArgs e)
{
this.demoThread =
new Thread(new ThreadStart(this.ThreadProcSafe));
this.demoThread.Start();
}
private void ThreadProcSafe()
{
int length = 10;
Parallel.For(1, length, j =>
{
//this.textBox1.Text = this.textBox1.Text + "Simulation Replication " + j.ToString() + "\r\n";
this.SetText("Simulation Replication " + j.ToString() + "\r\n");
}); // Parallel.For
}
private void SetText(string text)
{
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text = this.textBox1.Text + text;
}
}
これにより、目的の出力が生成されます。
シミュレーション レプリケーション 4
シミュレーション レプリケーション 2
シミュレーション レプリケーション 7
...
ただし、2 行目の代わりに並列 for ループ内の (現在コメントされている) 最初の行を使用しようとすると、次のエラーが発生します。
「クロススレッド操作が無効です: コントロール 'textBox1' は、それが作成されたスレッド以外のスレッドからアクセスされました。」
最初の質問は、並列計算 (Matlab で一部実行) が初めてで、Visual C# が初めての場合、このエラーは正確に何を伝えようとしているのかということです。私がやろうとしていることを達成する別の方法はありますか? 現在有効な方法よりも簡単ですか?
さて、私は別の問題も抱えています。これに対して提案された他の戦略を使用しようとしました。これは、非常によく似たコードで、バックグラウンド ワーカーを使用しています。メッセージを表示するだけで追加しない場合、すべて正常に動作します。追加しようとすると、5 つの並列計算が実行され、それらが表示され、GUI ギャングが表示されます... フリーズするだけで、エラーも何もなく、スタックします。私が使用しているコードは次のようになります (SetText は上記のコードと同じです)。
private void setTextBackgroundWorkerBtn_Click(object sender, EventArgs e)
{
this.backgroundWorker2.RunWorkerAsync();
}
private void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
int length = 10;
Parallel.For(1, length, k =>
{
//this.textBox1.Text = this.textBox1.Text + "Simulation Replication " + k.ToString() + "\r\n";
this.SetText("Simulation Replication " + k.ToString() + "\r\n");
}); // Parallel.For
}
実際には最初の 5 つのテキストを出力し、インデックスは 1,2,4,6,8 です。これらが厳密に増加しているという事実に何か関係がありますか?
上記のケースでこのコードが機能する理由を理解したいのですが、バックグラウンドワーカーを使用するとうまくいかないようです。バックグラウンドワーカーを使用する方が良い方法だと読みました。バックグラウンドワーカーを使用して目的の動作を実現する方法を教えてもらえますか?
最後に、これを行う最善の方法を知りたいだけです。多くの計算を伴う並列 for ループを実行している場合 (1 回の反復ですべての計算を実行するのに約 5 秒かかるとします)、反復の開始時に現在のインデックス番号を表示したい場合、それを行う最善の方法は何ですか?並列 for ループ内? これらの並列計算に到達する前に、テキストボックスにあったすべてのデータを保持したい...したがって、追加する必要があります..
ここでの助けやアドバイスは大歓迎です。コンソール アプリで出力をコンソールに書き込むように指示するのは簡単で、問題はありません (Matlab と C# の両方を使用)。テキスト ボックスを使用すると、問題が発生するようです。助けてください!