Visualizzazione dei risultati da 1 a 6 su 6
  1. #1
    Utente di HTML.it
    Registrato dal
    Jul 2006
    Messaggi
    455

    [C#]Problema con cross-thread

    Ciao a tutti,

    La mia applicazione deve ricevere dal mio server comandi da eseguire.

    In pratica,dal server dico al client di cambiare il valore di una variabile boolean.

    dal server invio la stringa "pass"

    il client la riceve ed esegue questa funzione:

    codice:
            private delegate void boolDelegate(bool var, Control ctrl,Form frm);
            private void _SetVar(bool var, Control ctrl, Form frm)
            {
                if (ctrl.InvokeRequired)
                {
                    boolDelegate bd = new boolDelegate(_SetVar);
                    frm.Invoke(bd, new object[] { var });
                }
                else
                {
                    ctrl.Enabled = var;
    
                }
            }
    Quando la funzione viene eseguita il client va in crash con questo errore:

    "Parameter count mismatch."

  2. #2
    Be', è normale, stai chiamando _SetVar (tramite il delegate e Invoke) passandole un solo argomento invece dei tre che richiede... correggi con
    codice:
                    frm.Invoke(bd, new object[] { var, ctrl, frm});
    e magari ripassa l'uso dei delegate e di Invoke per capire esattamente cosa fa e come funziona quella funzione, dato che ho l'impressione che non ti sia chiarissimo...
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Utente di HTML.it
    Registrato dal
    Jul 2006
    Messaggi
    455
    Originariamente inviato da MItaly
    Be', è normale, stai chiamando _SetVar (tramite il delegate e Invoke) passandole un solo argomento invece dei tre che richiede... correggi con
    codice:
                    frm.Invoke(bd, new object[] { var, ctrl, frm});
    e magari ripassa l'uso dei delegate e di Invoke per capire esattamente cosa fa e come funziona quella funzione, dato che ho l'impressione che non ti sia chiarissimo...
    Si non mi è chiarissimo di come funziona, ma ci sto lavorando su ^^

  4. #4
    Spiegazione rapida:
    i controlli Windows Forms non sono thread-safe, ovvero se li chiami da thread diversi da quello in cui sono stati creati (ovvero, il thread che gestisce il message loop della GUI) apri la porta a potenziali race-conditions; per questo motivo, tra le altre cose, c'è una protezione che solleva un'eccezione se provi a fare una chiamata cross-thread su controlli Windows Forms.
    Entra in gioco il metodo Control.Invoke.
    Control.Invoke serve a chiamare il metodo specificato (tramite delegate) dal thread della GUI, anche se la funzione che chiama Invoke si trova in un altro thread; in pratica questo accade facendo una SendMessage con un messaggio custom alla finestra in cui si trova il controllo specificato, ma quello che ti interessa è che il thread da cui chiami si mette in pausa e aspetta che il thread della GUI richiami la funzione specificata.
    Nasce quindi l'"idioma" della "ctrl.InvokeRequired": per scrivere una funzione che possa essere richiamata senza problemi da qualunque thread, la funzione, prima di operare su un controllo, gli chiede se è necessario fare una Invoke (ovvero, se non siamo nel thread GUI che lo gestisce) usando la ctrl.InvokeRequired. Se non è necessaria una Invoke (ovvero, siamo già nel thread corretto) la funzione prosegue a fare quello che deve fare (ovvero, quello che accade nell'else della tua funzione). In caso contrario, la funzione richiama sé stessa tramite la Invoke, ri-passandosi tutti i parametri; in questo caso, dato che la "nuova" chiamata è avvenuta tramite Invoke (e quindi siamo nel thread giusto) Control.InvokeRequired restituisce false e la funzione fa direttamente il suo mestiere.
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Utente di HTML.it
    Registrato dal
    Jul 2006
    Messaggi
    455
    Originariamente inviato da MItaly
    Spiegazione rapida:
    i controlli Windows Forms non sono thread-safe, ovvero se li chiami da thread diversi da quello in cui sono stati creati (ovvero, il thread che gestisce il message loop della GUI) apri la porta a potenziali race-conditions; per questo motivo, tra le altre cose, c'è una protezione che solleva un'eccezione se provi a fare una chiamata cross-thread su controlli Windows Forms.
    Entra in gioco il metodo Control.Invoke.
    Control.Invoke serve a chiamare il metodo specificato (tramite delegate) dal thread della GUI, anche se la funzione che chiama Invoke si trova in un altro thread; in pratica questo accade facendo una SendMessage con un messaggio custom alla finestra in cui si trova il controllo specificato, ma quello che ti interessa è che il thread da cui chiami si mette in pausa e aspetta che il thread della GUI richiami la funzione specificata.
    Nasce quindi l'"idioma" della "ctrl.InvokeRequired": per scrivere una funzione che possa essere richiamata senza problemi da qualunque thread, la funzione, prima di operare su un controllo, gli chiede se è necessario fare una Invoke (ovvero, se non siamo nel thread GUI che lo gestisce) usando la ctrl.InvokeRequired. Se non è necessaria una Invoke (ovvero, siamo già nel thread corretto) la funzione prosegue a fare quello che deve fare (ovvero, quello che accade nell'else della tua funzione). In caso contrario, la funzione richiama sé stessa tramite la Invoke, ri-passandosi tutti i parametri; in questo caso, dato che la "nuova" chiamata è avvenuta tramite Invoke (e quindi siamo nel thread giusto) Control.InvokeRequired restituisce false e la funzione fa direttamente il suo mestiere.
    Grazie mille adesso mi è tutto molto piu' chiaro.

  6. #6
    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.