C # Форма Windows, созданная EventHandler, исчезает немедленно - PullRequest
1 голос
/ 28 мая 2009

Я не знаю, почему это происходит, но когда я создаю новую форму внутри 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 ]

5 голосов
/ 28 мая 2009

Я полагаю, что проблема в том, что вы выполняете код в обработчике из своего пользовательского потока, а не потока пользовательского интерфейса, который необходим, поскольку он управляет насосом сообщений Windows. Вы хотите использовать метод Invoke, чтобы форма получалась и отображалась в потоке пользовательского интерфейса.

private void launchForm(object sender, EventArgs e)
{
    formThatAlreadyExists.Invoke(new MethodInvoker(() =>
    {
        mf = new myForm();
        mf.Show();
        MessageBox.Show("Do you see the form?");
    }));
}

Обратите внимание, что это предполагает, что у вас уже есть объект WinForms (называемый formThatAlreadyExists), который вы запустили с использованием Application.Run. Кроме того, может быть лучшее место, чтобы поместить вызов Invoke в ваш код, но это, по крайней мере, пример того, как его можно использовать.

1 голос
/ 28 мая 2009

это выглядит так, как если бы вы не были в потоке формы sta, поэтому, когда вы показываете, что форма пропала, и поток завершает свою работу, он убивает себя, так как ничто не ссылается на поток. Это не лучшее решение для этого, но вы можете использовать showdialog (), а не show, чтобы выполнить его сохранение состояния, если вам нужен пример кода, я использую этот же процесс для формы «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();
    }
}
1 голос
/ 28 мая 2009

Я думаю, что если вы создаете форму в потоке, форма принадлежит этому потоку. При создании любых элементов пользовательского интерфейса это всегда следует делать в основном потоке пользовательского интерфейса.

0 голосов
/ 04 июня 2009

Вы создали окно в потоке без пользовательского интерфейса. Когда поток прерывается, он забирает ваше окно вместе с ним. Конец истории. Выполните вызов в главной форме, передав делегата, который будет выполнять метод, который создает окно сообщения в потоке пользовательского интерфейса. Поскольку MessageBox является модальным окном, если вы не хотите, чтобы метод launchForm блокировал фоновый поток, создайте пользовательскую форму с требуемым пользовательским интерфейсом и вызовите show (), а не ShowDialog ().

0 голосов
/ 28 мая 2009

Is

dbf.Show();

опечатка? Это должно быть вместо этого?

mf.Show(); 

Возможно ли, что вы показываете другую форму, отличную от той, которую вы намереваетесь показать?

...