Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1
    Utente di HTML.it
    Registrato dal
    Aug 2012
    Messaggi
    12

    [C#]Variabile che cambia, genera evento.

    Salve a tutti.
    Sono nuovo del forum e perciò approfitto per fare una rapida presentazione su cosa faccio, anche per capire quali possono essere i miei limiti.
    Lavoro per una ditta che realizza apparecchiature elettroniche, ma non dirò il nome per ovvi motivi. Sono hardwarista e firmwarista allo stesso tempo in quanto progetto e realizzo macchine stand alone (intendo senza PC) che collaudano schede elettroniche. Sono una persona fortunatissima perchè il mio lavoro coincide con il mio hobby. Mi sento particolarmente specializzato in firmware e (come dicono i miei colleghi) sono uno degli ultimi martiri che programma preferibilmente in assembler. Mi sono imparato tutti i segreti di Atmel Freescale Microchip Texas ST ecc...
    Confesso che ho fatto molti lavori anche in ANSI C ma (sempre come dicono i miei colleghi) sono assuefatto dall'assembler.

    L'hobby mi ha portato quì. E' da un mesetto che mi sto studiando il C# grazie a un paio di libri acquistati di recente e ovviamente, da autodidatta ho qualche difficoltà.

    Ora spiego il mio progetto.

    Ho realizzato per conto mio una serie di trasponder per il cronometraggio delle moto su pista.
    Il progetto prevede 3 elementi:
    Trasmittente infrarossi:
    Trasmette un codice tramite dei led con angolo ristretto e viene posta nella riga del traguardo per identificare il giro.
    Trasponder:
    Vengono messi sulle moto e ricevono il segnale infrarosso della riga del traguardo e poi trasmettono in radiofrequenza (a 868MHz) il loro codice univoco.
    Ricevente:
    La ricevente gestisce le ricezioni e manda via porta COM al PC i risultati.

    Il progetto Funziona. L'ho testato nella pista di Tolmezzo con ottimi risultati e la cosa ha scatenato anche l'interesse di qualcuno.

    Per visualizzare i tempi del mio sistema sto usando l'HIPER TERMINAL, che è una cosa molto spartana. Funzionante ma spartana.

    Ecco quì la mia scelta di fare un programma in C#.
    La cosa sta proseguendo e sono già a un livello base dove ricevo i dati, li elaboro e li visualizzo su un datagridview.

    Ora io ho una cosa che mi assilla e vorrei capire se è possibile fare.
    In realtà non mi serve (ancora) ma la troverei utilissima.

    E' possibile, data una variabile, far si che quando essa cambia di valore, generi un evento?

    Faccio un esempio.
    Nel mio progetto, usando una seriale, si può facilmente gestire la ricezione con:

    public void Ricezione_dati_COM(object sender, SerialDataReceivedEventArgs e)

    Questo metodo immagino faccia parte della libreria. Non è una variabile. E' un evento generato da una ricezione seriale.
    Ma se io vovessi crearne uno simile che esegue le sue istruzioni quanda una varabile
    int variable
    cambia di valore è possibile?

    Grazie.

  2. #2
    Utente di HTML.it L'avatar di torn24
    Registrato dal
    Aug 2008
    Messaggi
    551

    ciao

    Si è possibile , è non è complicato , Quindi presumo di aver capito male la tua domanda , o
    che non ti sei spiegato molto bene

    se ad esempio disponi di una "variabile" meglio dire campo dichiarato all'interno della classe
    poi ne cambi il valore , basta controllare che il valore corrisponda a un determinato valore
    e richiamare il metodo che vuoi .
    per controllare il valore del campo , dipende da come è fatto il programma , se ad esempio
    devi controllare il valore del campo , in determinate situazioni lo farai all'interno di un metodo.
    se invece lo devi controllare a intervalli di tempo regolari , puoi usare un timer o meglio un
    controllo timer .




    un esempio , da la domanda come lo capita io
    usando un controllo timer



    codice:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            private int a = 0; //campo "variabile globale stile c"
            private int old = 0; //campo "variabile globale stile c"
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                timer1.Enabled = true;
                timer1.Interval = 2000; //intervallo di due secondi attiva il metodo timer
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
               //modifica in qualche modo il campo a 
                old = a;// memorizzo il valore di a in old
                a++; //modifico Campo a 
            }
    
            private void timer1_Tick(object sender, EventArgs e)
            {
                if (old != a)
                    MioMetodo();
                 old = a;//evita che venga sempre ripetuto la chiamata al metodo
            }
    
    
    
    
            private void MioMetodo()
            {
    
                MessageBox.Show("il campo a è stato modificato");
              
            }
        }
    }
    Tecnologia

  3. #3
    Una variabile no (a meno di non andare in polling come mostrato da torn, ma non è un metodo molto elegante)*; piuttosto, quello che puoi fare è incapsulare la tua variabile "dietro" una property, e nella property set generare l'evento subito dopo aver impostato la variabile.

    * in realtà probabilmente qualche trucco per farlo c'è, probabilmente usando qualche hook usata normalmente dai debugger, ma anche questo non mi pare un modo né elegante né efficiente.
    Amaro C++, il gusto pieno dell'undefined behavior.

  4. #4
    Utente di HTML.it
    Registrato dal
    Aug 2012
    Messaggi
    12
    Il polling con il timer non è quello che volevo.

    incapsulare la tua variabile "dietro" una property, e nella property set generare l'evento subito dopo aver impostato la variabile.
    Questo però è interessante e sicuramente da provare. Sembra un trucco per ottenere quello che voglio, ma è già qualcosa.

    Comunque, parlando in assembler è come se avessi una variabile assegnata a un registro che genera un interupt. Se il main agisce in scrittura a quella variabile, genera un interupt, e il programma salta nel vettore di interupt tornando dov'era quando ha finito.

    Certo che rileggendo quello che ho scritto mi sa di violare le regole di "programmazione orientata agli oggetti"... si ripresenta sempre la mia assuefazione all'assembler.

  5. #5
    Originariamente inviato da Arago
    Questo però è interessante e sicuramente da provare. Sembra un trucco per ottenere quello che voglio, ma è già qualcosa.
    È il metodo che si usa normalmente per avere questo genere di comportamenti.
    Comunque, parlando in assembler è come se avessi una variabile assegnata a un registro che genera un interupt. Se il main agisce in scrittura a quella variabile, genera un interupt, e il programma salta nel vettore di interupt tornando dov'era quando ha finito.
    In teoria in codice nativo puoi emulare questo genere di comportamento anche senza pasticciare direttamente con gli interrupt (cosa che ovviamente lavorando in user mode ti è assolutamente proibita, dato che gli interrupt sono gestiti dal sistema operativo) andando ad impostare la pagina di memoria della variabile come di sola lettura e catturando la relativa eccezione SEH che viene sollevata dal sistema operativo al tentativo di scrittura (di fatto staresti facendo una specie di emulazione di un page fault). Il problema è che in C# non credo che sia possibile in maniera semplice.
    Tieni conto che cercare di essere "troppo intelligenti" nello sfruttare caratteristiche hardware non è una buona idea se si lavora con linguaggi managed, dato che, di loro natura, nascono per essere platform-independent; di fatto, stai lavorando dentro una macchina virtuale che esegue codice IL, la quale a sua volta vive in uno spazio di indirizzi virtuale e il codice gira in user mode. Per questo motivo non hai molto spazio di manovra per paciugare direttamente con l'hardware, devi piuttosto cercare che soluzioni ti mette a disposizione il linguaggio e le sue eventuali librerie.
    Certo che rileggendo quello che ho scritto mi sa di violare le regole di "programmazione orientata agli oggetti"... si ripresenta sempre la mia assuefazione all'assembler.
    Amaro C++, il gusto pieno dell'undefined behavior.

  6. #6
    Utente di HTML.it
    Registrato dal
    Aug 2012
    Messaggi
    12
    Grazie MItaly sei stato di grande aiuto.

  7. #7
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    ciao, in .net esiste gia un interfaccia che fa al caso tuo: INotifyPropertyChanged.

    io te la ripropongo da zero cosi da farti vedere oltre che come usarla anche cosa effettivamente è (e come usare gli eventi in c#).

    codice:
    // Firma dell'evento il quale in realtà è una delegate che ritorna void e ha due argomenti in input
        // un riferimento all'oggetto scatenante di tipo object e un "bagaglio" di informazioni da mettere a disposizione dei subscriber
        // Il secondo oggetto è di tipo derivante da EventArgs.
        public delegate void CustomNotifierEventHandler(object sender, CustomNotifierTypeEventArgs e);
    
        // OPZIONALE. EventArgs specializzato per il nostro specifico evento.
        // L'oggetto conterrà tutte le info da passare ai sottoscritti
        // per esempio il nome della proprietà che è cambiata
        public class CustomNotifierTypeEventArgs : EventArgs
        {
            public string NomeProprieta { get; set; }
        }
    
        // Interfaccia da implementare dalle classi che vogliono "notificare" i cambiamenti alle loro proprietà
        public interface ICustomNotifierPropertyChanged
        {
            public event CustomNotifierEventHandler PropertyChanged;
        }
    
        // Classe di esempio.
        // La proprietà Variabile1 notificherà tramite evento ogni volta che subirà cambiamenti
        public class ClassManager : ICustomNotifierPropertyChanged
        {
            private int _variabile1;
            public int Variabile1
            {
                get
                {
                    return _variabile1;
                }
                set
                {
                    if (_variabile1 != value)
                    {
                        _variabile1 = value;
                        OnPropertyChanged("Variabile1");
                    }
                }
            }
    
            /// L'implementazione dell'interfaccia non è altro che la dichiarazione dell'evento
            public event CustomNotifierEventHandler PropertyChanged;
    
            public void OnPropertyChanged(string nomeProp)
            {
                // Salvare un evento in una var temporanea prima di usarlo è un pattern che ti mette
                // PARZIALMENTE al sicuro da eventuali problemi di sincronizzazione.
                var temp = PropertyChanged;
                if (temp != null)
                {
                    CustomNotifierTypeEventArgs e = new CustomNotifierTypeEventArgs { NomeProprieta = nomeProp };
                    temp(this, e);
                }
            }
        }

  8. #8
    Utente di HTML.it
    Registrato dal
    Aug 2012
    Messaggi
    12
    Ciao rsdpzed.
    Fa esattamente quello che volevo!!!

    Ho copiato e incollato il tuo codice e ho richiamato la Variabile1 in una mia funzione e messo un break point in
    codice:
    var temp = PropertyChanged;
    All'interno del mio programma ho istanziato la classe e ho dato un valore a Variabile1

    codice:
    ClassManager prova = new ClassManager();
    prova.Variabile1 = 1;
    ed effettivamente il programma è andato sul breack point.

    con un breck point su
    codice:
    prova.Variabile1 = 1
    Visul studio mi ha notificato che l'assegnazione di valore su quasta variabile ha provocato un'esecuzione di un'istruzione, routine, proprietà o operatore.

    Il compilatore mi dava un errore alla riga
    codice:
    public event CustomNotifierEventHandler PropertyChanged;
    ho dovuto mettere
    codice:
    event CustomNotifierEventHandler PropertyChanged;
    non mi accettava neanche il private

    Comunque questo è quello che cercavo.
    Ora devo studiami bene quello che hai fatto perchè lo voglio capire bene.

    Grazie

  9. #9
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    quello è stato un mio errore, i membri definiti in un interfaccia non hanno il modificatore di accesso (public, private...) non ha senso in quanto le classi che la implementeranno devono dichiararle obbligatoriamente public.
    Un interfaccia (le riconosci dal fatto che di solito iniziano con la I maiuscola) potremmo definirlo come un header (ora qualcuno mi fucilerà per questo) in cui dichiari delle "funzionalità". Una classe puo dichiarare a sua volta di voler implementare quelle funzionalita usando la notazione dell' ereditarietà. La nostra dichiara di voler implementare l'interfaccia ICustomNotifierPropertyChanged è cioè si impegna a dichiarare un evento di nome PropertyChanged.
    Questo fatto di mettere in mezzo un interfaccia è una pura scelta stilistica OOP. Funzionerebbe tutto anche senza. L'ho messa perche come dicevo esiste gia questo sistema e microsoft l'ha fatto cosi e mi è sembrato giusto farlo vedere in questo modo.

    la funzione OnPropertyChanged sarebbe meglio farla private, è una funzione "di servizio" ad uso e consumo della classe.

    Le delegate sono la controparte C# dei puntatori a funzione in C.

    Un EventHandler è una delegate con una signature specifica:

    void funzione(object sender, EventArgs e)

    per quanto riguarda EventArgs si puo usare un tipo derivato piu specifico (come l'esempio sopra) con lo scopo di inserire info aggiuntive ai subscriber da parte del publisher.

    in termini "C" dichiarare un evento in una classe è come dichiarare un array di puntatori a funzione. Sottoscriversi ad un evento in c# è come aggiungere il proprio puntatore a funzione dentro questo array.

    La classe che "possiede" l'evento ha la facoltà di chiamare l'evento in un qualche punto del codice come se fosse una funzione e internamente non fa altro che chiamare uno dopo l'altro le funzioni nell'array di puntatori a funzione.
    Dall'esterno sottoscriversi ad un evento significa "aggiungere" una funzione a questo array con la sintassi:

    oggetto.Evento += funzione;

    dove funzione è la funzione con la signature dell'evento (quella indicata poco sopra).

    Questo è quello che mi viene in mente sul codice, chiedi pure se ti serve qualcosa.

  10. #10
    Originariamente inviato da rsdpzed
    potremmo definirlo come un header

    (ora qualcuno mi fucilerà per questo)
    Amaro C++, il gusto pieno dell'undefined behavior.

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.