私は英語が苦手なので、質問を簡単に説明し、ここにコード スニペットを貼り付けて問題を説明します。
問題は、winForm アプリケーションのマルチスレッドの問題です。次のコードサンプルのようにロジックを単純化します。
テスト コードには、1 つの mainForm Form1 と、mainForm 内に「Start」という名前のボタンがあります。ユーザーがボタンをクリックすると、2 つのフォーム form2 と form3 が 2 つのバックグラウンド スレッドから表示されます。form2 が閉じられた後、Form1 が閉じられます。ただし、ここには form3 が表示されているため、ユーザーが自分で form3 を閉じる必要があります。そこで、form.Closing イベントを処理し、Application.DoEvents() を使用して、ユーザーが form3 を閉じられるようにしました。それは念頭に置いているように見えます。しかし実際には、form3 はユーザーのアクションを受け入れることができますが、form3 は期待どおりに閉じられません。
ここで form3 を閉じることができない理由と、ユーザーの閉じる操作が機能するようにコードを変更する方法を説明してください。
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
namespace CloseFormFromMainThread
{
public partial class Form1 : Form
{
private Form2 _form2;
private Form2 _form3;
private SynchronizationContext _synchronizationContext;
public Form1()
{
InitializeComponent();
Closing += Form1Closing;
}
void Form1Closing(object sender, CancelEventArgs e)
{
while (_form3 != null)
{
Application.DoEvents();
Thread.Sleep(100);
}
}
private void ButtonStartClick(object sender, EventArgs e)
{
var thread = new Thread(StartForm3);
thread.Start();
var thread2 = new Thread(StartForm2);
thread2.Start();
}
private void StartForm3()
{
Thread.Sleep(200);
var action = new Action(() =>
{
_form3 = new Form2();
_form3.Text = "form 3";
_form3.ShowDialog();
_form3 = null;
});
ExecuteActionInUiThread(action);
}
private void Form1Load(object sender, EventArgs e)
{
_synchronizationContext = SynchronizationContext.Current;
}
private void StartForm2()
{
Thread.Sleep(500);
var action = new Action(() =>
{
_form2 = new Form2();
_form2.Text = "form 2";
_form2.ShowDialog();
Close();
});
ExecuteActionInUiThread(action);
}
private void ExecuteActionInUiThread(Action action)
{
var sendOrPostCallback = new SendOrPostCallback(o => action());
_synchronizationContext.Send(sendOrPostCallback, null);
}
}
}