Invalid thread operation, Invoke method does not work

Asked

Viewed 74 times

1

I have an online chat code, in it there is a list of logged in users on the system. There is a problem when adding the name of users on listBox; The error is as follows: Operação entre threads inválida: controle 'lbClients' acessado de um thread que não é aquele no qual foi criado.

Codes:

public Principal()
    {
        InitializeComponent();
        clients = new ArrayList();
        processor = new Thread(new ThreadStart(StartListening));
        processor.Start();
    }

    public void StartListening()
    {
        listener = new TcpListener(listenport);
        listener.Start();
        while (true)
        {
            try
            {
                Socket s = listener.AcceptSocket();
                clientsocket = s;
                clientservice = new Thread(new ThreadStart(ServiceClient));
                //this.Invoke(new Action(() => ServiceClient()));
                clientservice.Start();
                //Iniciar += new EventHandler(ServiceClient);
                //Iniciar.Invoke();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
        //listener.Stop();
    }

    public void ServiceClient()
    {
        Socket client = clientsocket;
        bool keepalive = true;

        while (keepalive)
        {
            Byte[] buffer = new Byte[1024];
            client.Receive(buffer);
            string clientcommand = System.Text.Encoding.ASCII.GetString(buffer);

            string[] tokens = clientcommand.Split(new Char[] { '|' });
            Console.WriteLine(clientcommand);

            if (tokens[0] == "CONN")
            {
                for (int n = 0; n < clients.Count; n++)
                {
                    Client cl = (Client)clients[n];
                    SendToClient(cl, "JOIN|" + tokens[1]);
                }
                EndPoint ep = client.RemoteEndPoint;
                //string add = ep.ToString();
                Client c = new Client(tokens[1], ep, clientservice, client);
                this.Invoke(new Action(() => clients.Add(c)));
                string message = "LIST|" + GetChatterList() + "\r\n";
                SendToClient(c, message);

                lbClients.Items.Add(c);
            }
            else if (tokens[0] == "CHAT")
            {
                for (int n = 0; n < clients.Count; n++)
                {
                    Client cl = (Client)clients[n];
                    SendToClient(cl, clientcommand);
                }
            }
            else if (tokens[0] == "PRIV")
            {
                string destclient = tokens[3];
                for (int n = 0; n < clients.Count; n++)
                {
                    Client cl = (Client)clients[n];
                    if (cl.Name.CompareTo(tokens[3]) == 0)
                        SendToClient(cl, clientcommand);
                    if (cl.Name.CompareTo(tokens[1]) == 0)
                        SendToClient(cl, clientcommand);
                }
            }
            else if (tokens[0] == "GONE")
            {
                int remove = 0;
                bool found = false;
                int c = clients.Count;
                for (int n = 0; n < c; n++)
                {
                    Client cl = (Client)clients[n];
                    SendToClient(cl, clientcommand);
                    if (cl.Name.CompareTo(tokens[1]) == 0)
                    {
                        remove = n;
                        found = true;
                        lbClients.Items.Remove(cl);
                    }
                }
                if (found)
                    this.Invoke(new Action(() => clients.RemoveAt(remove)));
                client.Close();
                keepalive = false;
            }
            else
            {
                int remove = 0;
                bool found = false;
                int c = clients.Count;
                for (int n = 0; n < c; n++)
                {
                    Client cl = (Client)clients[n];
                    //SendToClient(cl, clientcommand);
                    if (cl.Name.CompareTo(tokens[1]) == 0)
                    {
                        remove = n;
                        found = true;
                        lbClients.Items.Remove(cl);
                    }
                }
                if (found)
                    clients.RemoveAt(remove);
                client.Close();
                keepalive = false;
            }
        }
    }

    public void SendToClient(Client cl, string message)
    {
        try
        {
            byte[] buffer = System.Text.Encoding.ASCII.GetBytes(message.ToCharArray());
            cl.Sock.Send(buffer, buffer.Length, 0);
        }
        catch (Exception e)
        {
            cl.Sock.Close();
            cl.CLThread.Abort();
            clients.Remove(cl);
            lbClients.Items.Remove(cl.Name + " : " + cl.Host.ToString());
        }
    }
    public string GetChatterList()
    {
        string chatters = "";
        for (int n = 0; n < clients.Count; n++)
        {
            Client cl = (Client)clients[n];
            chatters += cl.Name;
            chatters += "|";
        }
        chatters.Trim(new char[] { '|' });
        return chatters;
    }

Specifically in this part of the code that adds the user to the list:

if (tokens[0] == "CONN")
            {
                for (int n = 0; n < clients.Count; n++)
                {
                    Client cl = (Client)clients[n];
                    SendToClient(cl, "JOIN|" + tokens[1]);
                }
                EndPoint ep = client.RemoteEndPoint;
                //string add = ep.ToString();
                Client c = new Client(tokens[1], ep, clientservice, client);
                this.Invoke(new Action(() => clients.Add(c)));
                string message = "LIST|" + GetChatterList() + "\r\n";
                SendToClient(c, message);

                lbClients.Items.Add(c);
            }

And this one, which removes the user from the list:

else if (tokens[0] == "GONE")
            {
                int remove = 0;
                bool found = false;
                int c = clients.Count;
                for (int n = 0; n < c; n++)
                {
                    Client cl = (Client)clients[n];
                    SendToClient(cl, clientcommand);
                    if (cl.Name.CompareTo(tokens[1]) == 0)
                    {
                        remove = n;
                        found = true;
                        lbClients.Items.Remove(cl);
                    }
                }
                if (found)
                    this.Invoke(new Action(() => clients.RemoveAt(remove)));
                client.Close();
                keepalive = false;
            }

How to get around that mistake once I tried the Invoke but it didn’t work?

1 answer

1


Hello, Marlon. All right? Try this way and give us feedback! I added comments where I made the adjustments to your code.

      if (tokens[0] == "CONN") {
            for (int n = 0; n < clients.Count; n++)
            {
                Client cl = (Client)clients[n];
                SendToClient(cl, "JOIN|" + tokens[1]);
            }

            EndPoint ep = client.RemoteEndPoint;
            //string add = ep.ToString();
            Client c = new Client(tokens[1], ep, clientservice, client);
            this.Invoke(new Action(() => clients.Add(c)));
            string message = "LIST|" + GetChatterList() + "\r\n";
            SendToClient(c, message);

            this.Invoke(new Action(() => lbClients.Items.Add(c))); //CÓDIGO NOVO

            //lbClients.Items.Add(c); //CÓDIGO ANTIGO.
        }

And so.

else if (tokens[0] == "GONE")
        {
            int remove = 0;
            bool found = false;
            int c = clients.Count;
            for (int n = 0; n < c; n++)
            {
                Client cl = (Client)clients[n];
                SendToClient(cl, clientcommand);
                if (cl.Name.CompareTo(tokens[1]) == 0)
                {
                    remove = n;
                    found = true;

                    this.Invoke(new Action(() => lbClients.Items.Remove(cl))); //CÓDIGO NOVO
                   //lbClients.Items.Remove(cl); //CÓDIGO ANTIGO
                }
            }
            if (found)
                this.Invoke(new Action(() => clients.RemoveAt(remove)));
            client.Close();
            keepalive = false;
        }

Browser other questions tagged

You are not signed in. Login or sign up in order to post.