C # Winforms Threading - задерживает дочернее событие формы до закрытия формы - PullRequest
2 голосов
/ 22 сентября 2009

У меня есть интересная проблема .. У меня есть форма, которая запускает другую форму (2) через кнопку. Перед закрытием формы Form2 иногда запускается событие, которое аннулирует форму 1 и вынуждает форму 1 обновлять свои данные. У меня проблема в том, что после того, как форма 2 запустила событие, форма 1, кажется, получает его, обрабатывает и обновляет данные, и только после этого форма 2 закрывается. Я хочу, чтобы форма 2 запустила событие и закрыла, ДО того, как обработчик событий формы Form1 перехватит и обработает событие. У меня есть ощущение, что это связано с BackgroundWorker (вроде как SwingUtilities.InvokeLater в Java) .. но я не настолько опытен с этим ..

public class Frm1{

void LaunchForm2(){
   Frm2 form2 = new Frm2();
   form2.dataChanged += new DataChangeListener(myListener);
   form2.showDialog();
}
private void myListener(){
  //get my data again
}

}

public class Frm2{

 private void Close(){
    if(myDataHasChanged){
      if(dataChanged != null) { 
        dataChanged(); 
      }
      this.Close();
    }
 }
}

Ответы [ 5 ]

2 голосов
/ 23 сентября 2009

Вы можете сделать это в OnHandleDestroyed, как это было сделано после окончательного уничтожения дескриптора окна. Вы можете быть уверены, что:

  1. Frm2
  2. Звонок всегда будет вызываться при закрытии формы

Таким образом сделайте что-то вроде следующего:

public class Frm2 : Form
{
    protected override void OnHandleDestroyed(EventArgs e)
    {
        base.OnHandleDestroyed(e);
        if (myDataHasChanged)
        {
            if (dataChanged != null)
                dataChanged();
        }
    }
    private void Close()
    {
        if (myDataHasChanged)
            this.Close();
    }
}

UPDATE:

Проверка того, что HandleDisposed вызывается перед возвратом из ShowDialog ():

        bool called = false;

        Form test = new Form();
        test.Shown += delegate (Object o, EventArgs e) { test.Close(); };
        test.HandleDestroyed += delegate(Object o, EventArgs e) { called = true; };
        test.ShowDialog();

        Assert.IsTrue(called);
2 голосов
/ 23 сентября 2009

Есть ли конкретная причина, по которой вы используете события в этой ситуации?

Предоставьте в Form2 свойство, позволяющее проверить, изменились ли данные. После завершения вызова ShowDialog () проверьте значение свойства и при необходимости выполните обновление.

(Отредактировано для удаления моего теперь бесполезного примера кода.)

0 голосов
/ 23 сентября 2009

Попробуйте изменить вызов события на:

public class Frm2{

 private void Close(){
    if(myDataHasChanged){
      if(dataChanged != null) { 
        dataChanged.BeginInvoke(); 
      }
      this.Close();
    }
 }
}

Это не гарантирует закрытия формы до завершения myListener (). Однако следует разрешить закрытию формы, не дожидаясь завершения myListener ().

0 голосов
/ 23 сентября 2009

Вы можете вызвать событие после вызова Close - вызов Form.Close не завершит вызов метода, который его вызвал.

EDIT : попробуйте использовать BeginInvoke для ожидания следующего цикла сообщений перед обработкой события, например:

form2.dataChanged += delegate { BeginInvoke(new DataChangeListener(myListener)); };

2 nd EDIT : чтобы дать Form1 возможность перекрасить, дважды вызовите BeginInvoke для ожидания двух циклов сообщений перед обновлением (один для закрытия Form2, а второй для перекраски Form1) , вот так:

form2.dataChanged += delegate(parameters) { 
    BeginInvoke(new Action(delegate { 
        BeginInvoke(new DataChangeListener(myListener), parameters);
    }));
    //Or,
    BeginInvoke(new Func<Delegate, object[], IAsyncResult>(BeginInvoke),
                new object[] { parameters }
    );
};
0 голосов
/ 22 сентября 2009

Почему бы вам не вызвать событие DataChanged в закрытом событии формы 2?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...