我不知道为什么会这样,但是当我在EventHandler中创建一个新表单时,它会在方法完成后立即消失。
这是我的代码。为了清晰起见,我编辑了它,但从逻辑上讲,它完全相同。
static void Main()
{
myEventHandler = new EventHandler(launchForm);
// Code that creates a thread which calls
// someThreadedFunction() when finished.
}
private void someThreadedFunction()
{
//Do stuff
//Launch eventhandler
EventHandler handler = myEventHandler;
if (handler != null)
{
handler(null, null);
myEventHandler = null;
}
}
private void launchForm(object sender, EventArgs e)
{
mf = new myForm();
mf.Show();
MessageBox.Show("Do you see the form?");
}
private myForm mf;
private EventHandler myEventHandler;
只要MessageBox“你看到表单了吗?”就会显示新表单。在那儿。只要我单击“确定”,表单就会消失。
我错过了什么?我认为通过将新表单分配给类变量,它将在方法完成后保持活动状态。显然,事实并非如此。
答案 0 :(得分:5)
我认为问题在于您是从自定义线程执行处理程序中的代码,而不是 UI线程,这是必需的,因为它操作Windows消息泵。您希望在此处使用Invoke
方法来确保表单获取并显示在UI线程上。
private void launchForm(object sender, EventArgs e)
{
formThatAlreadyExists.Invoke(new MethodInvoker(() =>
{
mf = new myForm();
mf.Show();
MessageBox.Show("Do you see the form?");
}));
}
请注意,这假设您已经使用formThatAlreadyExists
运行了WinForms对象(称为Application.Run
)。此外,可能有更好的地方将Invoke
调用放入您的代码中,但这至少是可以使用它的一个示例。
答案 1 :(得分:1)
我认为如果在线程上创建表单,表单将由该线程拥有。在创建任何UI元素时,应始终在主(UI)线程上完成。
答案 2 :(得分:1)
这看起来好像你不在表单sta线程上,所以一旦你显示它已经消失并且线程完成它的工作就会自行杀死它,因为没有任何引用线程的东西。它不是最好的解决方案,但你可以使用showdialog()而不是一个节目来完成它保持状态,如果你需要一个代码示例我使用这个完全相同的过程“loading ....”形式
public class Loading
{
public delegate void EmptyDelegate();
private frmLoadingForm _frmLoadingForm;
private readonly Thread _newthread;
public Loading()
{
Console.WriteLine("enteredFrmLoading on thread: " + Thread.CurrentThread.ManagedThreadId);
_newthread = new Thread(new ThreadStart(Load));
_newthread.SetApartmentState(ApartmentState.STA);
_newthread.Start();
}
public void Load()
{
Console.WriteLine("enteredFrmLoading.Load on thread: " + Thread.CurrentThread.ManagedThreadId);
_frmLoadingForm = new frmLoadingForm();
if(_frmLoadingForm.ShowDialog()==DialogResult.OK)
{
}
}
/// <summary>
/// Closes this instance.
/// </summary>
public void Close()
{
Console.WriteLine("enteredFrmLoading.Close on thread: " + Thread.CurrentThread.ManagedThreadId);
if (_frmLoadingForm != null)
{
if (_frmLoadingForm.InvokeRequired)
{
_frmLoadingForm.Invoke(new EmptyDelegate(_frmLoadingForm.Close));
}
else
{
_frmLoadingForm.Close();
}
}
_newthread.Abort();
}
}
public partial class frmLoadingForm : Form
{
public frmLoadingForm()
{
InitializeComponent();
}
}
答案 3 :(得分:0)
是
dbf.Show();
一个错字?它应该是这样吗?
mf.Show();
是否有可能除了您打算展示的表格之外还有其他表格?
答案 4 :(得分:0)
您在非UI线程上创建了一个窗口。当线程中止时,它将带你的窗口。故事结局。 在主窗体上执行调用,传递委托,该委托将执行在UI线程上创建消息框的方法。 由于MessageBox是一个模态窗口,如果不希望launchForm方法阻塞后台线程,请创建一个带有所需UI的自定义表单并在其上调用show(),而不是ShowDialog()。