長い投稿で申し訳ありませんが、混乱が生じないように問題を詳細に説明しようとしました。最後の文には実際の質問が含まれています。
C#/。NETを使用してマルチスレッドアプリケーションをプログラミングしています。
このアプリケーションは、圧力センサーからのデータを視覚化するメインウィンドウで構成されています。センサーデータは独自のスレッドで取得されます。
データはクラスのインスタンスにも記録されますListView
:
「保存」ボタンを使用して、ログに記録されたデータをディスク上のファイルに保存する可能性があります(.NETクラスのインスタンスを開く必要がありますSaveFileDialog
)。
これSaveFileDialog
も独自のスレッドで実行されています。メソッドを呼び出すときに問題が発生しますSaveFileDialog.ShowDialog()
:
System.InvalidOperationExceptionが処理されませんでしたMessage="クロススレッド操作が無効です:コントロール'tlpMain'は、作成されたスレッド以外のスレッドからアクセスされました。" Source = "System.Windows.Forms"
SaveFileDialogの所有者(メインウィンドウ)が別のスレッドで実行されているため、問題が発生します。
SaveFileDialog()のスレッドを作成するコードは次のとおりです。
private void bSave_Click(object sender, EventArgs e)
{
Thread saveFileDialog = new Thread(OpenSaveFileDialog);
saveFileDialog.SetApartmentState(ApartmentState.STA);
saveFileDialog.Start();
}
メソッドOpenSaveFileDialog()のコード:
private void OpenSaveFileDialog()
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "Text Files (*.txt)|*.txt|CSV (*.csv)|*.csv|All Files (*.*)|*.*";
saveFileDialog.FilterIndex = 0;
/* Call "ShowDialog" with an owner ("this.Parent") to achieve, so that
* the parent window is blocked and "unclickable".
*
* Danger of an "InvalidOperationException" because "this.Parent" control
* is running (was created) in another thread.
* But "this.Parent" should not be modified by this method call.
*/
DialogResult pressedButton = saveFileDialog.ShowDialog(this.Parent);
...
InvalidOperationExceptionは、 VisualStudioのデバッガーでアプリケーションを実行している場合にのみスロー/表示されます。これまでのところ、アプリケーションを「正常に」実行する場合は問題ありません。
しかし、私はこの問題を避けたいと思います。
ラッパーメソッド(SaveFileDialog)を作成しようとしました:
private void OpenSaveFileDialog()
{
SaveFileDialog saveFileDialog = new SaveFileDialog();
...
SaveFileDialog(saveFileDialog, this.Parent);
}
ラッパーメソッド:
private void SaveFileDialog(SaveFileDialog saveFileDialog, Control owner)
{
if (owner.InvokeRequired)
BeginInvoke(new dSaveFileDialog(SaveFileDialog), new object[] { saveFileDialog, owner });
else
{
DialogResult pressedButton = saveFileDialog.ShowDialog(owner);
...
これによりTargetInvocationException
、Main()
メソッドには次のラベルが付けられ[STAThreadAttribute]
ますが、
InnerException:System.Threading.ThreadStateException Message = "OLE呼び出しを行う前に、現在のスレッドをシングルスレッドアパートメント(STA)モードに設定する必要があります。メイン関数にSTAThreadAttributeがマークされていることを確認してください。この例外は、デバッガーがプロセスに添付されています。」Source = "System.Windows.Forms"
SaveFileDialog
(スレッド)の問題を起こさずにメインウィンドウがブロックされる(「クリックできない」)ように、ある方法でを開く方法の手がかりを持っている人はいますか?
ありがとうございました。