0

I know that this exception is launched when a thread tries to edit a control of a form that it didn' t create, but I don't understand why I have this problem in this case. I have a form "Frm_Dupllicated" this is its code

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();
        */





    }
}

and this is what I do in the main Form that launches the exception

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


        }
    }

and this is where I run the From Duplicated (From the main form)

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

Using the debugger I realized That the exception is launched when I do this:

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

can you explain me why and How can I solve the problem? thanks

  • @Sriram Sakthivel Sorry but I don't understand how to solve the problem rwading the other answers cause in my case I don't know where to use InvokeRequired and Invoke 's methods. – Alessio Il Pierce Giannelli May 22 '15 at 10:51
  • 1
    How did you run/open/create/show this other form? Can you show the code that does that? – Lasse V. Karlsen May 22 '15 at 11:03
  • HI Lasse I have added the code in my question thanks for your Help – Alessio Il Pierce Giannelli May 22 '15 at 12:55
  • It looks like you're opening different forms on different threads. You must not do that - all WinForms UI must be done from the "UI thread", normally thread zero (except it's not thread zero when you're running under the Visual Studio debugger). – RenniePet May 22 '15 at 13:49
  • HI RenniePet thanks for your answer I decided to use a thread to open the form because I need the form to be opened while the main form is doing an other operation if I don't use the thread the from duplicated only appear after the main formed has finished the rendering operation and I don't want that – Alessio Il Pierce Giannelli May 22 '15 at 14:04
  • @RenniePet That's not entirely correct. You can have many threads running UI in a single application, it's mixing threads that will cause problems. As long as he doesn't access a form / ui control from a different thread than the one that created it he's fine. I would agree, however, that until he gets a grip on multithreading he should limit himself to one thread. – Lasse V. Karlsen May 22 '15 at 14:04
  • could I use the invokeRequired\invoke to solve the problem??? – Alessio Il Pierce Giannelli May 22 '15 at 14:05
  • If you need to access ui controls from a different thread, then yes, you should invoke a delegate so that you marshal some code onto the thread that owns the ui. – Lasse V. Karlsen May 22 '15 at 14:05
  • All of this is documented in the linked duplicate however. – Lasse V. Karlsen May 22 '15 at 14:06
  • @Lasse I still don't understand why the Apllication.OpenForms.OfType.First().Close() causes the exception I mean I don't edit any control of that form I just close it, am I wrong? – Alessio Il Pierce Giannelli May 22 '15 at 14:07
  • @Lasse but I don't understad in which method I should use the delegate ? in the Close() method can I do that? – Alessio Il Pierce Giannelli May 22 '15 at 14:10
  • Closing a from another thread owns will give you that exception, so yes, you need to invoke the close method. – Lasse V. Karlsen May 22 '15 at 14:44
  • @LasseV.Karlsen Thanks, point taken. – RenniePet May 22 '15 at 15:00
  • @Lasse this is how I solved the problem because I can't invoke Close (cause I can't find the code of the of the method) I made a method inside to duplicated from to call Close() and I have used a delegate for this function that I call from the main form.... – Alessio Il Pierce Giannelli May 22 '15 at 15:02

0 Answers0