似たような質問がたくさんあることを知っており、それらの多くを読みました。残念ながら、それらを読んでもまだ問題を解決できませんでしたが、私はC#に比較的慣れていません。ドキュメントによるとInvalidOperationException
、デバッガーを使用すると、スレッドセーフではないという問題が発生します。これは私の問題には当てはまりません。
問題に集中するために、単純な生のテスト クラスで問題を再現しました。
メイン フォームは、一種の進行状況ダイアログを表示することになっています。
public partial class ImportStatusDialog : Form
{
public ImportStatusDialog()
{
InitializeComponent();
}
public void updateFileStatus(string path)
{
t_filename.Text = path;
}
public void updatePrintStatus()
{
t_printed.Text = "sent to printer";
}
public void updateImportStatus(string clientName)
{
t_client.Text = clientName;
}
public void updateArchiveStatus()
{
t_archived.Text = "archived";
}
}
そのコードがメイン フォームから Invoke() なしで呼び出された場合:
private void button1_Click(object sender, EventArgs e)
{
ImportStatusDialog nDialog = new ImportStatusDialog();
nDialog.Show();
nDialog.updateFileStatus("test");
Thread.Sleep(1000);
nDialog.updateImportStatus("TestClient");
Thread.Sleep(1000);
nDialog.updatePrintStatus();
Thread.Sleep(1000);
nDialog.updateArchiveStatus();
Thread.Sleep(1000);
nDialog.Close();
}
そして、私がこのように呼んでも:
private void button3_Click(object sender, EventArgs e)
{
ImportStatusDialog nDialog = new ImportStatusDialog();
nDialog.Show();
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
nDialog.updateFileStatus("Test");
});
}
else
{
nDialog.updateFileStatus("Test");
}
Thread.Sleep(1000);
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
nDialog.updatePrintStatus();
});
}
else
{
nDialog.updatePrintStatus();
}
Thread.Sleep(1000);
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
nDialog.updateImportStatus("cName");
});
}
else
{
nDialog.updateImportStatus("cName");
}
Thread.Sleep(1000);
if (this.InvokeRequired)
{
this.Invoke((MethodInvoker)delegate
{
nDialog.updateArchiveStatus();
});
}
else
{
nDialog.updateArchiveStatus();
}
Thread.Sleep(1000);
nDialog.Close();
}
デザイナーでこのように見えるダイアログ(私の例では)
次のように表示されます。
Show( ) の代わりにShowDialog()を使用すると、ダイアログは正しく表示されますが、API Doc が指摘するように
このメソッドを使用して、アプリケーションでモーダル ダイアログ ボックスを表示できます。このメソッドが呼び出されると、その後のコードはダイアログ ボックスが閉じられるまで実行されません。
特にダイアログの更新は、ダイアログが再び閉じられた後にのみ行われることを意味するため、これは私が望むものではありません。
ここで何が間違っていますか?これは些細な問題のようですが、解決策は私を回避します。私は C# GUI プログラミングが初めてであることを覚えておいてください。
また、Invoke() を使用するのに適切な場所はどこでしょうか? ダイアログメソッドを呼び出すときにメインフォームで使用しますか、それともダイアログ更新メソッド自体で使用しますか?