Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C# / VB.NET - Aggiornare listbox da nuovo thread c#
Forum - C# / VB.NET - Aggiornare listbox da nuovo thread c#

Avatar
jaco94++ (Normal User)
Expert


Messaggi: 203
Iscritto: 22/10/2008

Segnala al moderatore
Postato alle 12:13
Domenica, 02/10/2011
Salve!

Come posso aggiungere un nuovo elemento in una listbox presente nel form da un nuovo thread in esecuzione?
Ho provato in questo modo ma non succede nulla e non si verificano neanche errori:

Codice sorgente - presumibilmente C++

  1. public class tsl:Finder
  2.         {
  3.             public void ls()
  4.             {
  5.                 TcpListener newex = null;
  6.                 Int32 port = 9100;
  7.                 IPAddress localAddr = IPAddress.Any;
  8.                 newex = new TcpListener(localAddr, port);
  9.  
  10.                 newex.Start();
  11.                 Byte[] bytes = new Byte[256];
  12.                 string Mid="";
  13.                 string name = "";
  14.                
  15.                 while (true)
  16.                 {
  17.                     TcpClient me = newex.AcceptTcpClient();
  18.                     if (me.Connected == true)
  19.                     {
  20.                         NetworkStream r_stream = me.GetStream();
  21.                         int i;
  22.                         while ((i = r_stream.Read(bytes, 0, bytes.Length)) != 0)
  23.                         {
  24.                             temp=System.Text.Encoding.ASCII.GetString(bytes,0,i);
  25.                         }
  26.                     }
  27.                     if (temp.Substring(0, 2) == "CD")
  28.                     {
  29.                         Mid = temp.Substring(2, 10);
  30.                         name = temp.Substring(12);
  31. // vengono eseguite ma non viene aggiunto nulla
  32.             listBox1.BeginUpdate();
  33.             listBox1.Items.Add(new { UserName = data1, MachineID = data2 });
  34.             listBox1.DisplayMember = "UserName";
  35.             listBox1.ValueMember = "MachineID";
  36.             listBox1.EndUpdate();
  37.                     }
  38.                 }
  39.  
  40.             }
  41.         }
  42. .
  43. .
  44. .
  45.  
  46.         private void Finder_Load(object sender, EventArgs e)
  47.         {
  48.             tsl tsl = new tsl();
  49.             Thread T_tsl = new Thread(tsl.ls);
  50.             T_tsl.Start();
  51. }


PM
Avatar
Il Totem (Admin)
Guru^2


Messaggi: 3635
Iscritto: 24/01/2006

Up
0
Down
V
Segnala al moderatore
Postato alle 13:06
Domenica, 02/10/2011
E' un errore banale. Tu hai istanziato un nuovo oggetto tsl che dispone delle proprie listBox, la quali NON sono le stesse del form Finder da cui richiami Form_Load. E' quindi ovvio che non vedi nessun cambiamento.

Comunque, per evitare eccezioni dovute a chiamate cross-thread, è bene usare Form.Invoke per far richiamare dal form un certo delegato. Tuttavia non puoi riferirti al form nel tuo codice perché ti trovi in un'ulteriore classe nidificata. Infatti il sorgente che hai scritto è pieno di errori di progettazione:

1. ls non fa mai riferimento a this, né a membri di classe, giacché tsl non contiene campi e non esiste nessuna variabile non dichiarata in ls. Quindi non ha senso creare una classe derivata. Il metodo ls può funzionare benissimo nella classe base.
2. while(true) spesso è indice di un comportamento errato. Sebbene possa rientrare comodamente nell'ambito delle richieste asincrone, usalo con cautela.
3. Accettare un nuovo TcpClient ad ogni iterazione è un enorme spreco di tempo e di memoria, così come creare un nuovo stream.
4. Il while restituisce solo la fine di un messaggio. Tutto ciò che viene prima dei 256 bytes finali viene perduto.
5. Mischi il livello logico con quello di presentazione (interfaccia grafica) nello stesso codice. Non dovresti accedere alle listbox, ma lanciare un evento in occorrenza del quale il form si aggiorna.

Ho corretto il codice e ho tolto la classe tsl che non mi serviva ora rimane solo la funzione ls che viene eseguita come nuovo thread, ho provato a documentarmi su invoke ma continuo a non capire come si usa e come richiamo la listbox - jaco94++ - 02/10/11 15:11
Devi richiamare this.Invoke (essendo nel form, this fa riferimento allo stesso), e passarle come parametro un delegato che punta alla funzione che si occupa di aggiornare la listbox. - Il Totem - 03/10/11 19:44
PM