Phenton Ответов: 1

Недопустимая операция потока, метод invoke не работает


У меня есть код онлайн-чата, есть список вошедших в систему пользователей. Существует проблема добавления имени пользователя в поле списка ошибка выглядит следующим образом: недопустимая операция потока: управление 'lbClients' осуществляется из потока, который не является тем, в котором он был создан.

Я попробовал вызвать метод, но он также не сработал. С помощью метода Invoke сервер добавляет пользователя в список, но когда пользователь отключается, список пользователей, вошедших на сервер, не обновляется. Что можно сделать?

Код:

public void StartListening()
    	{
    		listener = new TcpListener(listenport);
    		listener.Start();
    		while (true) {
    			try
    			{
    				Socket s = listener.AcceptSocket();
    				clientsocket = s;
                    clientservice = new Thread(new ThreadStart(ServiceClient));
                    clientservice.Start();
    			}
    			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);
                    try
                    {
                        lbClients.Items.Add(c);
                    }
                    catch (Exception e)
                    {
                        MessageBox.Show(e.Message);
                    }
    				
    			}
    			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);
    						//lbClients.Items.Remove(cl.Name + " : " + cl.Host.ToString());
    					}
    				}
    				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);
                            //lbClients.Items.Remove(cl.Name + " : " + cl.Host.ToString());
                        }
                    }
                    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());
    			//MessageBox.Show("Could not reach " + cl.Name + " - disconnected","Error",
    			//MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
    		}
    	}
        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;
    	}


Что я уже пробовал:

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))); //NEW CODE

            //lbClients.Items.Add(c); //OLD CODE
        }


и:

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))); //NEW CODE
                   //lbClients.Items.Remove(cl); //OLD CODE
                }
            }
            if (found)
                this.Invoke(new Action(() => clients.RemoveAt(remove)));
            client.Close();
            keepalive = false;
        }

F-ES Sitecore

Вы удалите таким же образом можно добавить с помощью вызова.

Phenton

Но это не работает в моем коде, сервер не удаляет отключенного пользователя...

1 Ответов

Рейтинг:
8

Gerry Schmitz

Добавьте любые новые "действия" в параллельную очередь; запустите фонового работника, чтобы очистить очередь и обновить список в событии reporting progress.

Если BGW уже запущен, просто добавьте его в очередь.