Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Prova GeForce NOW upgrade Blackwell: il cloud gaming cambia per sempre
Prova GeForce NOW upgrade Blackwell: il cloud gaming cambia per sempre
L'abbonamento Ultimate di GeForce NOW ora comprende la nuova architettura Blackwell RTX con GPU RTX 5080 che garantisce prestazioni tre volte superiori alla precedente generazione. Non si tratta solo di velocità, ma di un'esperienza di gioco migliorata con nuove tecnologie di streaming e un catalogo giochi raddoppiato grazie alla funzione Install-to-Play
Ecovacs Deebot X11 Omnicyclone: niente più sacchetto per lo sporco
Ecovacs Deebot X11 Omnicyclone: niente più sacchetto per lo sporco
Deebot X11 Omnicyclone implementa tutte le ultime tecnologie Ecovacs per l'aspirazione dei pavimenti di casa e il loro lavaggio, con una novità: nella base di ricarica non c'è più il sacchetto di raccolta dello sporco, sostituito da un aspirapolvere ciclonico che accumula tutto in un contenitore rigido
Narwal Flow: con il mocio orizzontale lava i pavimenti al meglio
Narwal Flow: con il mocio orizzontale lava i pavimenti al meglio
Grazie ad un mocio rotante che viene costantemente bagnato e pulito, Narwal Flow assicura un completo e capillare lavaggio dei pavimenti di casa. La logica di intellignza artificiale integrata guida nella pulizia tra i diversi locali, sfruttando un motore di aspirazione molto potente e un sistema basculante per la spazzola molto efficace sui tappeti di casa
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 27-02-2014, 19:43   #1
mirkus90
Member
 
L'Avatar di mirkus90
 
Iscritto dal: Oct 2007
Città: Monopoli(BA)
Messaggi: 218
[C#] - ProgresBar e label durante un ciclo non aggiornate

Salve,
Ho un problemino...premetto che sono agli albori di c# e mi sono cimentato in questo esercizietto. Dovrei aspettare 5 secondi e durante questa attesa mostrare l'avanzamento di una barra di progresso. Ciò che noto che l'aggiornamento non me lo fa in "tempo reale"...perchè ho notato che mettendo una modifica della label all'interno del ciclo, questa non viene modificata

Codice:
                        DateTime start = DateTime.Now;
			int stop ;
			int valore;
			stop=start.Second+5;
			progressBar1.Maximum=stop-1;
			progressBar1.Minimum=start.Second;
			valore=start.Second;
			
				while(valore<stop){
					
					progressBar1.Value=valore;
					start = DateTime.Now;
					if(valore != start.Second){
						valore=valore+1;
					}
					label1.Text="dentro";
				}

			label1.Text="fine";
Come si nota dal codice quando entra nel ciclo e mentre la progresbar progredisce si la label1 dovrebbe cambiare in "dentro" e una volta uscito dal ciclo dovrebbe cambiare in "fine" ma in realtà avviene il cambiamento solo in "fine".
Come può mai accadere questo?
__________________
NOSTRAVIS PRO CLASSEM - GrupAer -
mirkus90 è offline   Rispondi citando il messaggio o parte di esso
Old 01-03-2014, 09:05   #2
[Kendall]
Senior Member
 
L'Avatar di [Kendall]
 
Iscritto dal: Jul 2005
Città: Vicenza
Messaggi: 1570
Quote:
Originariamente inviato da mirkus90 Guarda i messaggi
Salve,
Ho un problemino...premetto che sono agli albori di c# e mi sono cimentato in questo esercizietto. Dovrei aspettare 5 secondi e durante questa attesa mostrare l'avanzamento di una barra di progresso. Ciò che noto che l'aggiornamento non me lo fa in "tempo reale"...perchè ho notato che mettendo una modifica della label all'interno del ciclo, questa non viene modificata

Codice:
                        DateTime start = DateTime.Now;
			int stop ;
			int valore;
			stop=start.Second+5;
			progressBar1.Maximum=stop-1;
			progressBar1.Minimum=start.Second;
			valore=start.Second;
			
				while(valore<stop){
					
					progressBar1.Value=valore;
					start = DateTime.Now;
					if(valore != start.Second){
						valore=valore+1;
					}
					label1.Text="dentro";
				}

			label1.Text="fine";
Come si nota dal codice quando entra nel ciclo e mentre la progresbar progredisce si la label1 dovrebbe cambiare in "dentro" e una volta uscito dal ciclo dovrebbe cambiare in "fine" ma in realtà avviene il cambiamento solo in "fine".
Come può mai accadere questo?
Quando si programmano applicativi con interfaccia grafica una delle cose da tenere sempre a mente è che l'utente NON vuole che l'interfaccia si blocchi, a prescindere dal motivo.
Il tuo codice è bloccante, quindi l'utente dovrà aspettare tutti i 5 secondi prima di poter interagire ancora con l'interfaccia.
Se nei test che stai facendo questo può non essere un problema, lo è in una applicazione reale, e per questo è buona norma abituarsi a scrivere il nostro codice con un certo occhio a questi fattori.
Nel tuo caso puoi rendere il tutto non bloccante, e decisamente più elegante nella scrittura, utilizzando un timer, e collegando al relativo evento "Elapsed" un gestore che si occupa di aggiornare l'interfaccia ogni volta che tale evento viene scatenato (puoi impostare tu il valore degli intervalli).
Oltre ad essere una maniera più corretta (in prospettiva futura) di affrontare il problema, è anche estremamente più performante che non gestire il tutto dentro un loop il cui codice, prima del completamente, viene eseguito una infinità di volte inutilmente.

Questo un esempio basilare:
Codice:
public partial class MainWindow : Window
    {
        public Timer timer;

        public MainWindow()
        {
            InitializeComponent();            
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            timer = new System.Timers.Timer(10);
            timer.Elapsed += (senderObj, eventArgs) => {
                // Fai qualcosa
            };
            timer.Start();
        }
    }
In questo caso vedi solo l'evento che scatena l'inizio del tutto, chiaramente da qualche parte ci sarà anche l'evento che lo farà finire.
Verosimilmente se il tutto è basato esclusivamente sul tempo puoi istanziarti uno StopWatch, farlo partire quando ne hai la necessità insieme al Timer, e all'interno dell'evento Elapsed verificare il tempo trascorso.
[Kendall] è offline   Rispondi citando il messaggio o parte di esso
Old 01-03-2014, 12:15   #3
mirkus90
Member
 
L'Avatar di mirkus90
 
Iscritto dal: Oct 2007
Città: Monopoli(BA)
Messaggi: 218
E se invece (dato che parlando con il "cliente" una barra progressiva non serve più di tanto) utilizzassi un secondo thread per avviare le operazioni da fare in modo che il secondo thread esegua le operazioni (invio dati via seriale) e il thread principale resti sempre attivo in modo che al click sul pulsante lo possa fermare. Io ho pensato di fare in questo modo, ma non sono sicuro che funzioni perchè noto che quando chiudo il thread continua a generare thread

Codice:
public class SendData
{
    // This method will be called when the thread is started.
    public void DoWork()
    {
    	byte[] ON = new byte[1] { 0x64 };
		byte[] OFF = new byte[1] { 0x6e };
		byte[] to_write = new byte[1] { 0x64 };
		int stop;
		int attuale;
		DateTime start;
				
		try{
    		serialPort.Open();
    	}
		catch (Exception ex){
    		Console.WriteLine("open() error: " + ex.Message);
    		Environment.Exit(1);
		}
        while (!_shouldStop)
        {
   			start = DateTime.Now;
			stop=start.Second+5;
			attuale=start.Second;
		
			while(attuale<stop){
				start = DateTime.Now;
				if(attuale != start.Second){
					attuale=attuale+1;
				}
			}
			
			serialPort.Write(to_write,0,1);
				
			if(to_write==ON){
				to_write=OFF;

			}
			else{
				to_write=ON;

			}
        }
        serialPort.Close();
 
    }
    public void RequestStop()
    {
        _shouldStop = true;
    }

    private volatile bool _shouldStop;
    SerialPort serialPort = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);
}

namespace prova
{
	
	/// <summary>
	/// Description of MainForm.
	/// </summary>
	/// 
	
	
	public partial class MainForm : Form
	{
		
		public MainForm()
		{
			//
			// The InitializeComponent() call is required for Windows Forms designer support.
			//
			InitializeComponent();
			string[] serialPorts = SerialPort.GetPortNames();
		
			foreach (string serialPort in serialPorts){
    			this.cbSerialBox.Items.Add(serialPort);
    			if(serialPort.Length != 0)
    				cbSerialBox.SelectedIndex = 0;
 			}
			
		}

		
		void Button1MouseClick(object sender, MouseEventArgs e)
		{
			SendData workerObject = new SendData();
        	Thread workerThread = new Thread(workerObject.DoWork);
        	
        	
			if(button1.Text=="start"){
			
			label1.Text="main thread: Starting worker thread...";
			workerThread.Start();
			button1.Text="stop";
			}
			else{
				workerObject. RequestStop();
				workerThread.Abort(workerObject);
				button1.Text="start";
			}
			
		}
		
		
		
		
	}
}
P.s.: Ho utilizzato il mio metodo di conteggio del tempo perchp preferisco prima far funzionare i thread per bene
__________________
NOSTRAVIS PRO CLASSEM - GrupAer -
mirkus90 è offline   Rispondi citando il messaggio o parte di esso
Old 01-03-2014, 14:37   #4
[Kendall]
Senior Member
 
L'Avatar di [Kendall]
 
Iscritto dal: Jul 2005
Città: Vicenza
Messaggi: 1570
Ora però la domanda è totalmente diversa da quella iniziale, ergo il problema cambia completamente.

Allora, come primo consiglio l'utilizzo della classe Thread è sconsigliabile.
È una classe che va ad agire a "basso" (le virgolette sono d'obbligo) livello.
Utilizza sempre, salvo rari classi, la sua astrazione, la classe Task, che gestisce diverse delle problematiche derivanti dal multithreading.
Seconda cosa, quando si parla di threading e cancellazione, la richiesta che fai alla funzione Abort() non puoi avere la certezza che venga eseguita (per una serie di motivi).

Quando si parla di multithreading e/o operazioni asincrone, si entra in un campo decisamente complesso (personalmente il più ostico che ho trovato finora nello studio della programmazione). Ti conviene studiare adeguatamente il tutto.

Solitamente, quando si avvia una operazione asincrona e si vuole avere la possibilità di cancellarla, si utilizza la tecnica dei "cancellation token", che è in parte simile a quanto hai scritto tu prendendo spunto dall'msdn.

Ti consiglio questa lettura, in passato mi è stata decisamente utile: http://blogs.msdn.com/b/csharpfaq/ar...cellation.aspx


Ultimo avviso: basarsi sulla label di un bottone per avviare/fermare/riavviare una operazione è decisamente sbagliato. Quando tu richiedi la cancellazione e cambi subito la label del bottone, non puoi essere sicuro che l'operazione asincrona sia conclusa. Pertanto, se tu ripremi il pulsante "Start" può benissimo essere che nel frattempo l'operazione precedente sia ancora in esecuzione.
In questi casi solo ed esclusivamente l'effettiva terminazione dell'operazione asincrona dovrebbe riabilitare il pulsante per iniziarne una di nuova, e tutte queste tecniche si riconducono alla corretta gestione dei Thread.

Quindi, riassumendo, prima di iniziare questa strada, impara per bene tutto ciò che ci sta dietro, acquista un volume (da questo punto di vista ti consiglio tutta la vita "C# in a Nutshell", acquisto che rifarei mille volte) o segui molte guide online, ma finchè non hai ben chiara la situazione non avventurarti in questo campo perchè potresti fare più danni che altro alla tua applicazione.
[Kendall] è offline   Rispondi citando il messaggio o parte di esso
Old 01-03-2014, 17:25   #5
mirkus90
Member
 
L'Avatar di mirkus90
 
Iscritto dal: Oct 2007
Città: Monopoli(BA)
Messaggi: 218
Ok...letto e compreso...ora mi sorge un piccolo dubbio...ovvero non riesco a trovare nulla che riesca ad aiutarmi...
Ho creato il mio bel taskA che mi genere quella specie di "loop" (ho assegnato a taskA il metodo doWork)...quando richiamo il mio RequestStop(), questo metodo dovrebbe cambiare la variabile nel doWork che viene eseguito nel taskA...in modo che termina la sua esecuzione e possa terminare il task...solo che non riesco a richiamare nel modo corretto il metodo RequestStop in modo che cambi quando voglio io
__________________
NOSTRAVIS PRO CLASSEM - GrupAer -
mirkus90 è offline   Rispondi citando il messaggio o parte di esso
Old 02-03-2014, 00:59   #6
djadry
Member
 
Iscritto dal: Dec 2009
Città: Varese
Messaggi: 274
Potresti provare fermando il thread in esecuzione.


Sent from my GT-I8750 using Tapatalk
__________________
#FollowMe!
AMD Ryzen 1700X, ASUS Crosshair VI Hero, 32 GB DDR4 Corsair Vengeance 3200, NVidia GTX 960, Samsung 970 PRO, Phanteks Enthoo EVOLV ATX TG, LC EKWB custom loop e un po' di RGB...
djadry è offline   Rispondi citando il messaggio o parte di esso
Old 02-03-2014, 08:09   #7
[Kendall]
Senior Member
 
L'Avatar di [Kendall]
 
Iscritto dal: Jul 2005
Città: Vicenza
Messaggi: 1570
Quote:
Originariamente inviato da mirkus90 Guarda i messaggi
Ok...letto e compreso...ora mi sorge un piccolo dubbio...ovvero non riesco a trovare nulla che riesca ad aiutarmi...
Ho creato il mio bel taskA che mi genere quella specie di "loop" (ho assegnato a taskA il metodo doWork)...quando richiamo il mio RequestStop(), questo metodo dovrebbe cambiare la variabile nel doWork che viene eseguito nel taskA...in modo che termina la sua esecuzione e possa terminare il task...solo che non riesco a richiamare nel modo corretto il metodo RequestStop in modo che cambi quando voglio io
`
La parte incriminata è questa:

Codice:
void Button1MouseClick(object sender, MouseEventArgs e)
{
      SendData workerObject = new SendData();
      Thread workerThread = new Thread(workerObject.DoWork);
      
      if (button1.Text=="start") {
            label1.Text="main thread: Starting worker thread...";
	    workerThread.Start();
	    button1.Text="stop";
      }
      else {
            workerObject. RequestStop();
	    workerThread.Abort(workerObject);
	    button1.Text="start";
      }
}

Qui vai a creare ad ogni click del pulsante un nuovo thread (o Task se hai modificato in tal senso), quindi quel RequestStop() andrà sempre e solo ad agire nel nuovo Task creato, non quello originario del primo click.

Il problema pertanto è che il Task NON và dichiarato lì, ma come campo privato della classe, così che ogni azione venga fatta sempre su di esso.
All'interno del pulsante andrai solo ad istanziare il nuovo Task e SOLO SE un altro non è già attivo (quindi non all'inizio del corpo dell'evento ButtonClick).

PS: Io userei come ti accennavo prima un approcio diverso comunque. E precisamente lo sfruttare i meccanismi di asincronia resi disponibili dal linguaggio.
Fai una ricerca riguardo alle parole async e await (in relazione al c#), e molte cose ti saranno più chiare.

Ultima modifica di [Kendall] : 02-03-2014 alle 08:20.
[Kendall] è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Prova GeForce NOW upgrade Blackwell: il cloud gaming cambia per sempre Prova GeForce NOW upgrade Blackwell: il cloud ga...
Ecovacs Deebot X11 Omnicyclone: niente più sacchetto per lo sporco Ecovacs Deebot X11 Omnicyclone: niente più...
Narwal Flow: con il mocio orizzontale lava i pavimenti al meglio Narwal Flow: con il mocio orizzontale lava i pav...
Panasonic 55Z95BEG cala gli assi: pannello Tandem e audio senza compromessi Panasonic 55Z95BEG cala gli assi: pannello Tande...
HONOR Magic V5: il pieghevole ultra sottile e completo! La recensione HONOR Magic V5: il pieghevole ultra sottile e co...
Intel resuscita Comet Lake: arriva il 'n...
Xiaomi 15 Ultra con lenti Leica e HyperA...
La gamma del Kobo Clara Colour si aggior...
Microsoft e OpenAI, accordo preliminare ...
Due Smart TV LG in offerta su Amazon: OL...
Due scope elettriche super accessoriate ...
Intel perde un altro pezzo da novanta: a...
Scende al prezzo impossibile di 149€ il ...
SK hynix svela la mostruosa HBM4, la mem...
ECOVACS non si ferma più e conqui...
Da non credere: crolla a 899€ MacBook Ai...
ASUS ROG porta in Italia una nuova tasti...
Samsung Galaxy S26 Ultra: brutte notizie...
Cos'è RSL, il nuovo standard che ...
Nissan Micra EV: da 29.500 a oltre 36.00...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 08:20.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Served by www3v