他のスレッドから WinForms オブジェクトに対して form.show()
を呼び出すと、フォームが例外をスローします。 メインアプリのスレッドに新しい、目に見えるフォームを追加できる方法はありますか? そうでなければ、現在実行中のスレッドを停止せずにフォームを開くにはどうしたらよいでしょうか?
以下は私のサンプルコードです。 私は、スレッドを開始し、そのスレッド内でいくつかの作業を実行しようとしています。 作業が進むにつれて、フォームを表示するようにします。
public void Main()
{
new Thread(new ThreadStart(showForm)).Start();
// Rest of main thread goes here...
}
public void showForm()
{
// Do some work here.
myForm form = new myForm();
form.Text = "my text";
form.Show();
// Do some more work here
}
invokeコールを使ってみてください。
public static Form globalForm;
void Main()
{
globalForm = new Form();
globalForm.Show();
globalForm.Hide();
// Spawn threads here
}
void ThreadProc()
{
myForm form = new myForm();
globalForm.Invoke((MethodInvoker)delegate() {
form.Text = "my text";
form.Show();
});
}
この呼び出しは、フォームに "invoke"Please execute this code in your thread rather than mine." と伝えます。
Invokeに関するより詳しいドキュメントはこちらです: http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx
編集: invokeを呼び出すには、すでに存在するWinFormsオブジェクトを使用する必要があります。 ここでは、グローバルオブジェクトを作成する方法を示しましたが、他のウィンドウオブジェクトがあれば、それらも同様に機能します。
form.Show()を呼び出した後に
Application.Run()` を呼び出す必要があります。例えば
public void showForm()
{
// Do some work here.
myForm form = new myForm();
form.Text = "my text";
form.Show();
Application.Run();
// Do some more work here
}
詳しい理由については、この msdn の記事を参照してください。
私の経験上、一番いい方法です。
var ac = (ReportPre)Application.OpenForms["ReportPre"];
Thread shower = new Thread(new ThreadStart(() =>
{
if (ac == null)
{
this.Invoke((MethodInvoker)delegate () {
ac = new ReportPre();
ac.Show();
});
}
else
{
this.Invoke((MethodInvoker)delegate
{
pictureBox1.Visible = true;
});
if (ac.InvokeRequired)
{
ac.Invoke(new MethodInvoker(delegate {
ac.Hide();
ac.Show();
}));
}
}
}));
shower.Start();