由於我的英語不好,我簡單解釋我的問題,並在此處粘貼代碼片段來描述問題。C#Application.DoEvents不能在我的應用程序中工作
這個問題是我們的winForm應用程序中的一個多線程問題。我簡單的邏輯如下面的代碼示例。
在測試代碼中,mainForm中有1個mainForm Form1和一個名爲「Start」的按鈕。當用戶點擊按鈕時,將從2個後臺線程中顯示form2和form3兩個表單。 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);
}
}
}
爲什麼使用線程?一切似乎都運行在UI線程上?第1步是擺脫所有不必要的複雜性並刪除線程。然後你就有機會看到你的程序真的做了什麼。 –
實際代碼不應該需要Thread.Sleep()。而且GUI始終是1個線程,不要試圖做到這一點。 –
@HenkHolterman:這是行不通的。 WinForms不支持多線程。它只會崩潰。 – PMF