Domanda

Sto lavorando su un'app WinForms e ho un controllo utente in essa. I pulsanti nel controllo utente generano eventi fino al modulo che deve essere gestito da altro codice. Uno dei pulsanti avvia alcuni processi che causeranno problemi se vengono eseguiti contemporaneamente. Ho una logica nel codice per gestire lo stato, quindi in genere un utente non può eseguire il processo se è già in esecuzione. Tuttavia, se l'utente fa doppio clic sul pulsante, avvierà il processo due volte così rapidamente che è difficile per me impedirlo.

Mi chiedo, qual è il modo migliore per gestirlo?

Ho iniziato disabilitando il pulsante nell'evento click ma il secondo clic arriva prima che il primo clic provochi la disabilitazione del pulsante. L'impostazione di altri flag nel codice non l'ha catturato neanche.

Sto pensando di aggiungere una sorta di blocco della sincronizzazione al codice che genera l'evento, ma mi chiedo se qualcuno di voi abbia un'idea migliore.

Dato che questo progetto è per lo più completo, sto cercando risposte che non comportino una riscrittura radicale dell'app (come l'implementazione del blocco dell'applicazione composita), tuttavia, sono libero di pubblicare anche queste idee poiché posso usarle in i miei prossimi progetti.

È stato utile?

Soluzione

Assicurati che il tuo pulsante di disabilitazione o qualsiasi altro blocco che fai sia la / prima / cosa che fai nel gestore dell'evento. Sarei estremamente sorpreso se potessi mettere in coda due eventi click anche prima che vengano attivate le prime istruzioni, ma suppongo che sia possibile se sei su un computer molto lento impantanato con altre app.

In tal caso, utilizzare una bandiera.

private bool runningExclusiveProcess = false;

public void onClickHandler(object sender, EventArgs e)
{
    if (!runningExclusiveProcess)
    {
        runningExclusiveProcess = true;
        myButton.Enabled = false;

        // Do super secret stuff here

        // If your task is synchronous, then undo your flag here:
        runningExclusiveProcess = false;
        myButton.Enabled = true;
    }
}

// Otherwise, if your task is asynchronous with a callback, then undo your flag here:
public void taskCompletedCallback()
{
    runningExclusiveProcess = false;
    myButton.Enabled = true;
}

Se riesci ancora a ottenere due clic su qualcosa del genere, assicurati di non essere iscritto per sbaglio a un evento doubleClick, o qualsiasi altra cosa stia succedendo.

Altri suggerimenti

Stai gestendo l'evento due volte?

Sono molto sorpreso di leggere che sta arrivando il secondo clic prima di poter disabilitare il pulsante. Vorrei assicurarmi che non si stia collegando due volte all'evento. L'ho fatto per caso prima. Riceverai quindi due eventi, quasi istantaneamente.

Il flag di disabilitazione su quel pulsante non verrebbe impostato fino al completamento del gestore eventi del pulsante e tutti i clic aggiuntivi verranno messi in coda nella coda dei messaggi di Windows dietro il primo clic. Assicurarsi che il gestore eventi pulsante si completi rapidamente per liberare il thread dell'interfaccia utente. Esistono diversi modi per farlo, ma tutti implicano che l'eather genera un thread o mantiene un thread di lavoro pronto e in attesa di un AutoResetEvent.

Per caso, stai etichettando il pulsante con un'icona? Sicuramente usa il codice per impedire l'esecuzione di due processi contemporaneamente, ma puoi ridurre il doppio clic sul lato umano se il tuo pulsante appare e si comporta come un pulsante di comando convenzionale (rettangolare, solo etichetta di testo, "superficie sollevata" che si preme su un clic). Solo un pensiero.

Disabilita il pulsante non appena viene cliccato. Quindi, l'evento non può essere gestito due volte. Non appena l'evento è stato gestito, puoi riattivare il pulsante.

La risposta selezionata è vicina, se non addirittura aneddotica. A chi non lo sapesse manca troppo codice per avere un senso. Ho scritto un articolo sull'uso di timer e thread e l'esempio di codice è DAVVERO facile da capire. Prova a leggerlo e vedi se puoi impostare i flag dall'esempio sopra eseguendo il tuo processo di attività in un nuovo thread:

http://www.robault.com/category/Threading.aspx

Disabilita il pulsante dopo che l'utente lo ha fatto clic per la prima volta e prima di iniziare l'attività. Al termine dell'attività, riattivare il pulsante.

  

Ho iniziato disabilitando il pulsante   nell'evento click ma nel secondo   il clic arriva prima del primo clic   fa disabilitare il pulsante.   L'impostazione di altri flag nel codice no   prendilo neanche.

Dato che WinForms è intrinsecamente a thread singolo, non dovrebbe essere possibile far scattare il secondo clic prima che l'elaborazione per il primo sia stata completata (a meno che non si utilizzino nuovi thread o BackgroundWorker ecc.)

Puoi mostrarci un esempio che illustra il tuo problema?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top