c#由Close()引起的交叉线程操作异常为什么?

时间:2015-05-22 10:19:51

标签: c# multithreading exception

我知道当一个线程试图编辑一个它没有的表单的控件时会启动这个异常。创造,但我不明白为什么在这种情况下我有这个问题。我有一个表格" Frm_Dupllicated"这是它的代码

public partial class Frm_Duplicated : Form
{
    GroupBox gb;
    List<List<int>> a;
    List<int> entitiesToDelete;
    List<Entity> CurrentEntity;
    List<int> cE;
    int lines;
    int coloums;
    int loop = 0;
    bool Update = false;
    public bool canIclose = false;
    public Frm_Duplicated(ref List<List<int>> a, ref List<Entity> e,ref List<int> c)
    {
        InitializeComponent();
        this.a = a;
        cE = c;
        CurrentEntity = e;
        entitiesToDelete = new List<int> { };
    }

    private void label1_Click(object sender, EventArgs e)
    {

    }

    private void IdEnForm_Load(object sender, EventArgs e)
    {



        refreshForm();



    }

    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {

    }

    private void button1_Click(object sender, EventArgs e)
    {


    }

    private void button1_MouseClick(object sender, MouseEventArgs e)
    {

        if (button1.Text != "ok")
        {

            //
            int c = panel1.Controls.Count;
            for (int y = 0; y < c; y++)
            {

                if (panel1.Controls[y] is CheckBox)
                {
                    if (((panel1.Controls[y] as CheckBox).Checked)) Update = true;
                }
            }

            if (Update)
            {
                int d = panel1.Controls.Count;
                for (int y = 0; y < d; y++)
                {

                    if (panel1.Controls[y] is CheckBox)
                    {
                        if (!((panel1.Controls[y] as CheckBox).Checked))
                        {

                            entitiesToDelete.Add(int.Parse((panel1.Controls[y] as CheckBox).Name));
                            // MessageBox.Show("" + entitiesToDelete.Last());
                        }
                    }
                    }
                    //////////////////////////////////////////////////////////////////////

                    // what I want to obtain is that at every step I delete the entities selected

                    deleteDuplicatedEntities();
                    /* if (System.Windows.Forms.Application.OpenForms["Frm_Main"] != null)
                     {

                         (System.Windows.Forms.Application.OpenForms["Frm_Main"] as Frm_Main).RefreshWorkArea(true, true);


                     }*/
                    /////////////////////////////////////////////////////////
                    loop++;
                    Update = false;
                    refreshForm();


                }

            }

        else
        {
            cE.Clear();
            deleteDuplicatedEntities();
            // it gives an thread crossing operation exception
            if (System.Windows.Forms.Application.OpenForms["Frm_Main"] != null)
            {

                (System.Windows.Forms.Application.OpenForms["Frm_Main"] as Frm_Main).RefreshWorkArea(true, true);


            }
            canIclose = true;
            this.Close();

        }
    }

    private void IdEnForm_ResizeBegin(object sender, EventArgs e)
    {

    }

    private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
    {

    }
    private void getLayerFromid(int id, ref String s)
    {

        for (int i = 0; i < CurrentEntity.Count; i++)
        {
            if (id == CurrentEntity[i].Id)
            {


                s = CurrentEntity[i].GetLayerName();
            }


        }


    }

    private void label2_Click(object sender, EventArgs e)
    {

    }
    private void refreshForm()
    {

        String s = null;

        int c = panel1.Controls.Count;
       /* for (int y = 0; y < c; y++)
        {

            if (panel1.Controls[y] is CheckBox)
            {
                if (!((panel1.Controls[y] as CheckBox).Checked))
                {

                    entitiesToDelete.Add(int.Parse((panel1.Controls[y] as CheckBox).Name));
                    // MessageBox.Show("" + entitiesToDelete.Last());
                }
                else
                {



                }
            }

        }*/


        for (int i = c - 1; i >= 0; i--) panel1.Controls.Remove(panel1.Controls[i]);



        cE.Clear();

        if (loop < a.Count)
        {
            coloums = 20;
            lines = 20;

            for (int j = 0; j < a[loop].Count; j++)
            {


                CheckBox duplicated_cb = new CheckBox();
                duplicated_cb.Name = "" + a[loop][j];

   ///////////////////////////////////////////////////////             
                cE.Add(a[loop][j]);

////////////////////////////////////////////////////////////
                duplicated_cb.Width = 200;


                Point p = new Point(coloums, lines);

                lines = lines + 30;
                duplicated_cb.Location = p;



                getLayerFromid(a[loop][j], ref s);
                if (s != null)
                {




                    duplicated_cb.Text = "id= " + a[loop][j] + " layer= " + s;
                    duplicated_cb.ForeColor = Color.White;


                }

                panel1.Controls.Add(duplicated_cb);
                if (System.Windows.Forms.Application.OpenForms["Frm_Main"] != null)
                {

                    (System.Windows.Forms.Application.OpenForms["Frm_Main"] as Frm_Main).RefreshWorkArea(true, true);


                }
            }
           // if (loop != 0) button2.Visible = true;

        }
        else
        {
            this.Controls.Remove(label3);
            label2.Text = "there are no more duplicated entities";
            label2.ForeColor = Color.White;
            Label finalLabel = new Label();
            finalLabel.ForeColor = Color.White;
            Point p2 = new Point(12, 30);
            finalLabel.Location = p2;
            finalLabel.Text = "Click ok to delete the duplicated entities";
            finalLabel.Width = 300;
            this.Controls.Add(finalLabel);

            button1.Text = "ok";
           //if(loop!=0) button2.Visible = true;
        }


    }

    private void groupBox1_Enter(object sender, EventArgs e)
    {

    }
    private void deleteDuplicatedEntities()
    {

        for (int i = 0; i < entitiesToDelete.Count; i++)
        {

      // at this point I delete the entity (those their id is in the list entities to delete) from the list current entity      
            for (int j = 0; j < CurrentEntity.Count; j++)
                if (entitiesToDelete[i] == CurrentEntity[j].Id) CurrentEntity.RemoveAt(j);
            {    //MessageBox.Show("sto eliminando l'entità "+entitiesToDelete[i]);                    

            }
        }

        //if (button1.Text == "ok")
       // {
            for (int x = 0; x < entitiesToDelete.Count; x++)
            // here I delete the entity that the user has decided to delete from the list of the duplicated entities
            {
                for (int f = 0; f < a.Count; f++)
                {
                    for (int g = 0; g < a[f].Count; g++) if (entitiesToDelete[x] == a[f][g])
                        {
                            // MessageBox.Show("sto eliminando dalla lista " + a[f][g]); 
                            a[f].RemoveAt(g); g = g - 1;
                        }

                }



            }


        // I update the list a becase if there is an only entity left that is not a duplicated anymore
            for (int q = 0; q < a.Count; q++) if (a[q].Count <= 1) { a.RemoveAt(q); q = q - 1; loop--;//added in a  second moment }
            entitiesToDelete.Clear();



       }

            cE.Clear();
            if (System.Windows.Forms.Application.OpenForms["Frm_Main"] != null)
            {

                (System.Windows.Forms.Application.OpenForms["Frm_Main"] as Frm_Main).RefreshWorkArea(true, true);


            }

}

    private void IdEnForm_FormClosing(object sender, FormClosingEventArgs e)
    {
        // I don't want the user to manually close the form
        if (!canIclose)
        {
           canIclose = false;
            // I stop the user from closing the form manually
            if (e.CloseReason == CloseReason.UserClosing)
                e.Cancel = true;
        }


    }

    private void button2_Click(object sender, EventArgs e)
    {
       /* loop = loop - 1;
        int howmanyBack=0;
        int c = panel1.Controls.Count;
        for (int y = 0; y < c; y++)
        {

            if (panel1.Controls[y] is CheckBox)
            {
                if (((panel1.Controls[y] as CheckBox).Checked)) howmanyBack++;
            }
        }

        for (int i = 0; i < howmanyBack; i++) entitiesToDelete.RemoveAt(entitiesToDelete.Count - 1);
        refreshForm();
        */





    }
}

这就是我在启动异常的主窗体中所做的事情

 private void Frm_Main_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (Application.OpenForms.OfType<Frm_Duplicated>().Any())
        {
            Application.OpenForms.OfType<Frm_Duplicated>().First().canIclose = true;
            Application.OpenForms.OfType<Frm_Duplicated>().First().Close();


        }
    }

这是我运行From Duplicated(从主窗体)

的地方
if (CurrentProject.idofe.Count != 0)
                            {

                                   CurrentTread = new Thread(() => LaunchIdEnForm());
                                    CurrentTread.Name = "LaunchIdEnForm";
                                    CurrentTread.Start();


                           }

  private void LaunchIdEnForm()
    {

        // PROVVISORIA
        bool launch=true;
        if(launch){
        Form f = new Frm_Duplicated(ref CurrentProject.idofe, ref CurrentProject.entities,ref currentEntities);
        f.ShowDialog();
        launch=false;
        }

使用调试器我意识到当我这样做时会启动异常:

 Application.OpenForms.OfType<Frm_Duplicated>().First().Close();

你能解释一下我为什么以及如何解决这个问题? 感谢

0 个答案:

没有答案