由EventHandler创建的C#Windows窗体立即消失

时间:2009-05-28 16:34:31

标签: c# winforms multithreading .net-2.0 event-handling

我不知道为什么会这样,但是当我在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“你看到表单了吗?”就会显示新表单。在那儿。只要我单击“确定”,表单就会消失。

我错过了什么?我认为通过将新表单分配给类变量,它将在方法完成后保持活动状态。显然,事实并非如此。

5 个答案:

答案 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()。