Visualizzazione dei risultati da 1 a 7 su 7
  1. #1

    [C#] Thread e oggetti per riferimento

    Questa è difficile

    Dunque, sto cercando, e con non poche difficoltà, di passare ad un Thread il riferimento ad un oggetto Windows.Form, nello specifico una Label.

    L'idea è questa, il Thread è uno ed asincrono, senza bloccare l'applicazione devo attendere un determinato tempo prima di avviare una certa funzione, quindi ho pensato, per coinciare, di provare a modificare in maniera asincrona il testo di una Label.

    codice:
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                Prova_Thread pt = new Prova_Thread(ref this.label1);
                Thread th = new Thread(pt.Esegui);
                th.Start();
                while (!th.IsAlive) ;
                th.Join();
            }
        }
    
        public class Prova_Thread
        {
            private volatile Label _Lbl;
            private int _Conta;
            public Prova_Thread(ref Label Lbl)
            {
                this._Lbl = Lbl;
                this._Conta = 5;
            }
    
            public void Esegui()
            {
                while (this._Conta > 0)
                {
                    this._Lbl.Text = this._Conta.ToString();
                    this._Conta--;
                }
            }
        }
    Come vedete al Click di button1 creao un Thread, al quale passo per riferimento la label1, successivamente avvio il Thread.

    Internamente il Thread funziona bene finché non arriva all'istruzione this._Lbl.Text = this._Conta.ToString();

    Quì s'incarta.

    Ho già tentato in passato con oggetti come array o simili e mi è andata bene, ma questa è la prima volta che provo con oggetti strutturati come una Label.

    Avete suggerimenti?

    Grazie

  2. #2
    Che senso ha passare via reference un oggetto che già di suo è un riferimento?
    Inoltre ti ricordo che gli oggetti Windows Forms non sono thread safe, per cui accedervi da un altro thread causa un'eccezione in quanto non è sicuro.
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Mh, già, quello lo avevo visto, come si potrebbe ovviare a questo problema?

    In sostanza, questo è solo un esperimento che sto facendo per poter ottenere cose migliori in futuro, potrei pensare ad un orologio.

    Voglio una label che mi mostra sempre l'ora corrente, per se dovessi utilizzare il Thread.Sleep() metterei in blocco l'intera applicazione.

    Vorrei trovare un sistema tale che mentre un label si autoaggiorna posso fare altro...

  4. #4
    Puoi usare un normale timer, oppure utilizzare il solito metodo Invoke per richiamare una funzione nel contesto del thread proprietario della GUI; maggiori informazioni qui.
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Tnx!

    Si, effettivamente ho trovato qualcosa riguardo l'Invoke ma per certi versi è un pò castrante, non riesco ad usarlo come vorrei io.

    In compenso con il Timer invece ho ottenuto qualcosa di funzionale e al contempo semplice.

    Va comunque usato l'Invoke anche in questo caso altrimenti da l'eccezione cross-threading, ma è semplice.

    codice:
            delegate void SetTextCallback(string text);
    
            private void button1_Click(object sender, EventArgs e)
            {
                System.Threading.Timer tm = new System.Threading.Timer(new TimerCallback(Esegui));
                tm.Change(2000, 0);
            }
    
            private void Esegui(object Tmr)
            {
                System.Threading.Timer timer = (System.Threading.Timer)Tmr;
                timer.Dispose();
                this.SetText("Eseguito");
            }
    
            private void SetText(string text)
            {
                if (this.textBox1.InvokeRequired)
                {
                    SetTextCallback d = new SetTextCallback(SetText);
                    this.Invoke(d, new object[] { text });
                }
                else
                {
                    this.textBox1.Text = text;
                }
            }
    Una volta premuto button1 viene avviato un Timer che attende 2 secondi prima di eseguire l'operazione su texBox1.

    Durante questi 2 secondi l'applicativo risulta utilizzable e non rallentato.

  6. #6
    Invece di System.Threading.Timer (che richiama il callback in un thread separato) ti converrebbe usare il System.Windows.Forms.Timer, che è implementato a livello di messaggio inviato alla finestra, e quindi esegue il callback direttamente nel thread GUI; usando quest'ultimo, pertanto, non devi usare l'invoke.
    Amaro C++, il gusto pieno dell'undefined behavior.

  7. #7
    Acc, hai ragione, mi sono andato ad arrampicare sugli specchi quando a fianco c'era la scala mobile

    E' comeil timer del vb6, grazie!

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.