C#Winforms线程 - 延迟子表单事件直到表单关闭

时间:2009-09-22 19:53:32

标签: c# winforms multithreading

我有一个有趣的问题.. 我有一个Form通过Button启动另一个Form(2)。在Form2关闭之前,它有时会触发一个使表单1无效的事件并强制表单1刷新它的数据。我遇到的问题是在表单2触发事件后,表单1似乎得到它并处理它,并刷新它的数据并且只有表单2关闭。我希望Form 2触发事件并关闭,在Form1的事件处理程序捕获并处理事件之前。 我觉得它与BackgroundWorker有点相似(有点像Java中的SwingUtilities.InvokeLater)..但我对它没有经验......

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 个答案:

答案 0 :(得分:2)

您是否有在这种情况下使用事件的具体原因?

在Form2上公开一个属性,允许您检查数据是否已更改。 ShowDialog()调用返回后,检查属性的值并在必要时进行更新。

(编辑删除我现在无用的代码示例。)

答案 1 :(得分:2)

您可以在OnHandleDestroyed中执行此操作,因为它在最终销毁窗口句柄后完成。你可以肯定:

  1. Frm2
  2. 将不再进行任何处理
  3. 表单关闭时将始终触发调用
  4. 因此执行以下操作:

    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();
        }
    }
    

    更新:

    测试以验证在从ShowDialog()返回之前调用HandleDisposed:

            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 :(得分:0)

为什么不在form2的Closed事件中引发DataChanged事件?

答案 3 :(得分:0)

您可以在致电Close后举起活动 - 调用Form.Close不会退出调用它的方法。

编辑:在处理事件之前尝试使用BeginInvoke等待下一个消息循环,如下所示:

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

2 nd 编辑:为了给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 }
    );
};

答案 4 :(得分:-1)

尝试将事件调用更改为:

public class Frm2{

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

这不保证在myListener()完成之前表单关闭。但是,它应该允许表单关闭而不等待myListener()完成。