想问一个关于多线程中事件注销和事件处理的问题。
场景如下:
有一个主窗体Main_Form 和一个子窗体Sub_Form 还有一个类Long_Process。在Long_Process中有一个事件叫做OnIndexChanged,还有一个Run方法,此方法中跑了一个1到100的循环,在循环中每次都会触发OnIndexChanged事件。首先在Main_Form的构造函数中注册Long_Process的OnIndexChanged事件,在事件的处理函数中通过Invoke方法更新Main_Form中的一个TextBox内容,然后在Main_Form中点击一个按钮此按钮打开一个Sub_Form,并将自身的Long_Process对象传入Sub_Form,同样的在Sub_Form中也注册Long_Process的OnIndexChanged事件,并且在事件处理函数中也通过Invoke更新自身的一个TextBox,并在Sub_Form的FormClosed时注销OnIndexChanged。最后在Main_Form中点击另一个按钮用一个线程来启动Long_Process的Run方法。现在问题来了当我在Long_Process.Run的循环还没有跑完时关闭Sub_Form。按理说Main_Form的TextBox还应该会继续更新,但是有时候Main_Form的TextBox会不更新了(不是每次都是这样)。通过跟踪代码发现是有时候当在关闭Sub_Form时触发的注销Long_Process.OnIndexChanged动作时恰好Sub_Form的Long_Process.OnIndexChanged处理函数正在执行过程中。导致Long_Process.Run函数中的循环无法继续执行,会阻塞在if(OnIndexChanged!=null)OnIndexChanged()中。想求教有没有遇见过类似问题及如何安全的解决此问题。多谢多谢。大致代码如下//Main_Form大致代码
private Long_Process;
private Thread Worker;
public Main_Form()
{
   Long_Process Process = new Long_Process();
   Process.Event_OnIndexChanged += new Long_Process.DelegateOnIndexChangedHandler(OnIndexChanged);
   Worker = new Thread(new ThreadStart(Process.Run));
   Worker.IsBackground = true;
}private void OnIndexChanged(int index)
{
   if(!InvokeRequired)
   {
      this.TextBox1.Text = index;
   }
   else
      Invoke(new DelegateOnIndexChangedHandler(OnIndexChanged),new object[]{index});
}private void OnButton1Click(object sender, EventArgs e)
{
   Worker.Start();
}private void OnButton2Click(object sender, EventArgs e)
{
   Sub_Form sub = new Sub_Form(Process);
   sub.Show();
}
//Sub_Form大致代码
private Long_Process _Process;
public Sub_Form(Long_Process Process)
{
   _Process = Process;
   _Process.Event_OnIndexChanged += new Long_Process.DelegateOnIndexChangedHandler(OnIndexChanged);
}private void OnIndexChanged(int index)
{
   if(!InvokeRequired)
   {
      this.TextBox1.Text = index;
   }
   else
      Invoke(new DelegateOnIndexChangedHandler(OnIndexChanged),new object[]{index});
}private void SubForm_FormClosed(object sender, FormClosedEventArgs e)
{
   //可能是因为此处引起的Long_Process.Run中的循环无法再继续
   _Process.Event_OnIndexChanged -= new Long_Process.DelegateOnIndexChangedHandler(OnIndexChanged);
}
//Long_Process大致代码
public class Long_Process
{
   public delegate void DelegateOnIndexChangedHandler(int index);
   public event DelegateOnIndexChangedHandler Event_OnIndexChanged;   public void Run()
   {
      for(int i=1;i<=100;i++)
      {
         if(Event_OnIndexChanged!=null)
            Event_OnIndexChanged(i);//当有时候注销Sub_Form中的事件监听后会阻塞在这里,循环无法再继续。
      }
   }
}

解决方案 »

  1.   

    试下这个?public void Run()
            {
                for (int i = 1; i <= 100; i++)
                {
                    DelegateOnIndexChangedHandler temp = Event_OnIndexChanged;
                    if (temp != null)
                    {
                        Delegate[] subscribers = temp.GetInvocationList();
                        foreach (Delegate _subscriber in subscribers)
                        {
                            DelegateOnIndexChangedHandler subscriber = (DelegateOnIndexChangedHandler) _subscriber;
                            subscriber.BeginInvoke(i, null, null);
                        }
                    }
                }
            }
      

  2.   

    因为在Event_OnIndexChanged(i),刚好主线程有个事件要脱链,所以出错。
    加个锁就可以了:
                    lock (Event_OnIndexChanged)
                    {
                        if (Event_OnIndexChanged != null)
                        {
                            Event_OnIndexChanged(i);//当有时候注销Sub_Form中的事件监听后会阻塞在这里,循环无法再继续。
                        }
                    }
      

  3.   


    //SubForm_FormClosed 这个事件是窗体关闭后执行,好像我遇到过,换成这个SubForm_FormClosing 会好点