none
passaggio parametri tra due Thread

    Domanda

  • Buongiorno, avrei la necessità di passare dei parametri letti da seriale appartenenti ad un thread ad un secondo thread che mi gestisce un grafico per poter visualizzare i valori appena letti, ogni intervallo di tempo quindi effettuo le letture da seriale, e quando il dato viene letto lo vorrei passare al secondo thread, solo che alla prima lettura tutto ok, le successive non riesco ad aggiornare i valori inviati al grafico, ossia mi rimane con il valore precedente, quindi solo quello della prima lettura, spero si possa capire quello che ho in mente, qualcuno può darmi delucidazioni in merito alla gestione dei thread? 

    public delegate void secondario(string valore);
    
    public Form1()
            {
                InitializeComponent();
                
                timer.Elapsed += new ElapsedEventHandler(timer_Trascorso);
            }
    
    
    public void thread_secondario(string valore)
            {
                if (this.InvokeRequired)
                {               
                    secondario delegateMethod = new secondario(this.thread_secondario);
                    this.Invoke(delegateMethod, new object[] { valore });                        
                }
    
                else
                {
                    if (!secondo_aperto)
                    {
                        Form2 secondo = new Form2(valore);
                        secondo.Show();
                        secondo_aperto = true;
                    }
                    else if (secondo_aperto)
                    {
                        string a = "2";
                        Form2 secondo = new Form2(a);
                        //secondo.Refresh();
                        //secondo.Update();
                    }
                }
            }
    void timer_Trascorso(object sender, ElapsedEventArgs e)
            {
                PollFunction();
            }
    
    private void PollFunction()
            {
                
                DoGUIClear();
                pollCount++;
                DoGUIStatus("Poll count: " + pollCount.ToString());
    
                
                short[] values = new short[Convert.ToInt32(txtRegisterQty.Text)];
                ushort pollStart;
                ushort pollLength;
    
                if (txtStartAddr.Text != "")
                    pollStart = Convert.ToUInt16(txtStartAddr.Text);
                else
                    pollStart = 0;
                if (txtRegisterQty.Text != "")
                    pollLength = Convert.ToUInt16(txtRegisterQty.Text);
                else
                    pollLength = 20;
    
                
                try
                {
                    while (!mb.SendFc3(Convert.ToByte(txtSlaveID.Text), pollStart, pollLength, ref values)) ;
                }
                catch(Exception err)
                {
                    DoGUIStatus("Errore lettura ");
                }
    
                string itemString;
    
                switch (dataType)
                {
                    case "Decimale":
                        for (int i = 0; i < pollLength; i++)
                        {
                            itemString = "[" + Convert.ToString(pollStart + i + 40001) + "] , MB[" +
                                Convert.ToString(pollStart + i) + "] = " + values[i].ToString();
                            DoGUIUpdate(itemString);
                            thread_secondario(values[i].ToString());
                        }
    .
    .
    .
    

    grazie in anticipo

    martedì 10 maggio 2016 09:14

Risposte

  • Allora, ho deciso di creare un articolo per spiegare alcune cose e per darti modo di vedere il codice funzionante, creando l'esempio ho scoperto il motivo di tutti i tuoi problemi con il multithreading che dal tuo codice non sono chiari.

    l'Articolo si trova qui:

    Come passare un dato da una form ad un altra e aggiornare un valore a video nella form ricevente

    Assieme allo zip contenente la soluzione con l'esempio completo.

    Ti mostra anche come risolvere i tuoi problemi relativi al multithreading in modo più semplice di quanto tu abbia fatto utilizzando ove possibile System.Windows.Forms.Timer al posto di System.Timers.Timer visto che il primo è nato per essere usato sulla UI e quindi è già automaticamente Thread Safe.

    spero di averti chiarito un po' le idee, posta pure ulteriori domande sui thread se vuoi capirne di più.


    Sabrina C. - http://www.dotnetwork.it

    • Contrassegnato come risposta Morpheus88r venerdì 13 maggio 2016 09:47
    mercoledì 11 maggio 2016 10:36

Tutte le risposte

  • Innanzi tutto, la porzione di codice che mostri non è multi threading, ed ha un errore fondamentale nel fatto che se hai un form aperto, devi aggiornare il form aperto e non generarne comunque uno nuovo come fai tu nel

       else if (secondo_aperto)
                   
    {
                       
    string a = "2";
                       
    Form2 secondo = new Form2(a);
                       
    //secondo.Refresh();
                       
    //secondo.Update();
                   
    }

    Devi mettere la variabile secondo a livello di classe e magari fare qualcosa del tipo

    private Form2 secondo = null;
    
    public void thread_secondario(string valore)
    {
    	if (this.InvokeRequired)
    	{
    		secondario delegateMethod = new secondario(this.thread_secondario);
    		this.Invoke(delegateMethod, new object[] { valore });
    	}
    
    	else
    	{
    		if (secondo == null)
    		{
    			secondo = new Form2();
    			secondo.Show();
    			secondo.ValueShown = valore;
    
    		}
    		else 
    		{
    			secondo.ValueShown = valore;
    		}
    	}
    }

    Nella Form 2 posto che esista una TextBox che si chiama textValue questo è il codice da usare

    public string ValueShown
    {
    	get
    	{
    		return txtValue.Text;
    	}
    	set
    	{
    		txtValue.Text = value;
    	}
    }

    Detto tutto ciò, magari spiegaci che cosa hai intenzione di mettere in un thread separato, e come vuoi gestirlo.

    Intanto, ti racconto un pochino come usualmente lavoro io con i thread:

    Se ho 2 thread che devono accedere ad uno stesso oggetto (inteso come istanza di una classe) l'oggetto condiviso lo creo nel thread principale, in modo che venga reso visibile a tutti i thread lanciati. Dopo di che, tutti i thread che utilizzano l'oggetto, effettuano un Lock quando lo modificano in modo tale che le modifiche siano thread safe.

    Faccio un esempio:

    Io ho una Coda Dati (potrebbe essere un generic Queue per davvero), potrei avere più thread che vi accedono, il minimo potrebbe essere 2 un thread che inserisce dati ed un thread che toglie dati alla coda.

    La Coda Dati viene inserita in una classe QueueManager come oggetto a livello di classe, i metodi che utilizzano i thread, vengono poi fatti partire dalla classe manager, e nel momento in cui un thread deve aggiornare la coda (aggiungendo o togliendo un elemento) effettua un Lock della coda stessa prima di aggiornare e poi sblocca l'oggetto.

    In questo modo gli oggetti in coda sono sempre modificati in modo thread safe.

    Non so se ho reso l'idea ma magari dacci una serie di indicazioni più dettagliate e ti posso fare un esempio.

    HTH


    Sabrina C. - http://www.dotnetwork.it



    martedì 10 maggio 2016 17:52
  • inanzitutto grazie Sabrina, la porzione che avevo postato riguarda il problema che avevo riguardo il passaggio di parametri al form, in quanto non sapevo bene come gestirla per la parte di passaggio di parametri a form2 già aperto, quindi volevo virare verso una classe statica come risorsa comune per appunto condividere dati. Secondo te è la soluzione più congeniale? in ogni caso, il flusso di lavoro che volevo ottenere in poche parole è: ogni tot minuti con time.elapsed avvio un thread che va ad effettuare la lettura della seriale, il quale dopo aver letto mi salva tale lettura, banale, ma non avendo molta esperienza di thread anzi praticamente nulla volevo prima di tutto imparare a trattarli, più che altro per la parte di rilascio delle risorse, il mio dubbio/non conoscenza è se in una cosa di questo tipo sia più sicuro usare gli invoke e delegate o thread da terminare con join una volta salvata la lettura.




    • Modificato Morpheus88r mercoledì 11 maggio 2016 08:55
    mercoledì 11 maggio 2016 07:27
  • Allora, ho deciso di creare un articolo per spiegare alcune cose e per darti modo di vedere il codice funzionante, creando l'esempio ho scoperto il motivo di tutti i tuoi problemi con il multithreading che dal tuo codice non sono chiari.

    l'Articolo si trova qui:

    Come passare un dato da una form ad un altra e aggiornare un valore a video nella form ricevente

    Assieme allo zip contenente la soluzione con l'esempio completo.

    Ti mostra anche come risolvere i tuoi problemi relativi al multithreading in modo più semplice di quanto tu abbia fatto utilizzando ove possibile System.Windows.Forms.Timer al posto di System.Timers.Timer visto che il primo è nato per essere usato sulla UI e quindi è già automaticamente Thread Safe.

    spero di averti chiarito un po' le idee, posta pure ulteriori domande sui thread se vuoi capirne di più.


    Sabrina C. - http://www.dotnetwork.it

    • Contrassegnato come risposta Morpheus88r venerdì 13 maggio 2016 09:47
    mercoledì 11 maggio 2016 10:36
  • Grazie mille Sabrina
    venerdì 13 maggio 2016 09:47