Compact Framework/Filettatura - MessageBox visualizzata al di sopra di altri controlli dopo l'opzione prescelta

StackOverflow https://stackoverflow.com/questions/10071

Domanda

Sto lavorando su un app che afferra e installa un sacco di aggiornamenti via un un server esterno, e hanno bisogno di qualche aiuto con la filettatura.L'utente segue questo processo:

  • Click il pulsante
  • Metodo di verifica la presenza di aggiornamenti, conte è tornato.
  • Se è maggiore di 0, quindi chiedere all'utente se si desidera installare utilizzando MessageBox.Show().
  • Se sì, si attraversa un ciclo e chiamare BeginInvoke() il metodo run() di ogni aggiornamento per l'esecuzione in background.
  • Il mio aggiornamento di classe ha alcuni eventi che vengono utilizzati per aggiornare una barra di avanzamento, etc.

La barra di avanzamento aggiornamenti sono belle, ma il MessageBox non è completamente cancellato dallo schermo perché l'aggiornamento loop inizia proprio dopo che l'utente fa clic su sì (vedi screenshot qui sotto).

  • Cosa devo fare per rendere il messagebox scompaiono immediatamente prima dell'aggiornamento ciclo inizia?
  • Dovrei usare i Thread invece di BeginInvoke()?
  • Dovrei fare l'aggiornamento iniziale di controllo su un thread separato e chiama MessageBox.Show() da quel thread?

Codice

// Button clicked event handler code...
DialogResult dlgRes = MessageBox.Show(
    string.Format("There are {0} updates available.\n\nInstall these now?", 
    um2.Updates.Count), "Updates Available", 
    MessageBoxButtons.YesNo, 
    MessageBoxIcon.Question, 
    MessageBoxDefaultButton.Button2
);

if (dlgRes == DialogResult.Yes)
{
    ProcessAllUpdates(um2); 
}

// Processes a bunch of items in a loop
private void ProcessAllUpdates(UpdateManager2 um2)
{
    for (int i = 0; i < um2.Updates.Count; i++)
    {
        Update2 update = um2.Updates[i];

        ProcessSingleUpdate(update);

        int percentComplete = Utilities.CalculatePercentCompleted(i, um2.Updates.Count);

        UpdateOverallProgress(percentComplete);
    }
}

// Process a single update with IAsyncResult
private void ProcessSingleUpdate(Update2 update)
{
    update.Action.OnStart += Action_OnStart;
    update.Action.OnProgress += Action_OnProgress;
    update.Action.OnCompletion += Action_OnCompletion;

    //synchronous
    //update.Action.Run();

    // async
    IAsyncResult ar = this.BeginInvoke((MethodInvoker)delegate() { update.Action.Run(); });
}

Screenshot

Windows Mobile Bug

È stato utile?

Soluzione

L'interfaccia utente non è un aggiornamento perché tutto il lavoro che sta accadendo nel thread di interfaccia utente.La tua chiamata a:

this.BeginInvoke((MethodInvoker)delegate() {update.Action.Run(); }) 

sta dicendo richiamare l'aggiornamento.Azione.Run() del thread che ha creato "questo" (form), che è il thread di interfaccia utente.

Application.DoEvents()

sarà davvero dare il thread dell'interfaccia utente la possibilità di ridisegnare lo schermo, ma sarei tentato di creare un nuovo delegato, e chiamare BeginInvoke su questo.

Questo verrà eseguito l'aggiornamento.Azione.Funzione Run() su un thread separato stanziati dal pool di thread.Si può quindi mantenere il controllo IAsyncResult fino a quando l'aggiornamento è completo, l'interrogazione l'aggiornamento in oggetto per i suoi progressi dopo ogni controllo (perché non si può avere un altro thread aggiornare la barra di avanzamento/UI), poi la chiamata di Applicazione.DoEvents().

Si si suppone anche per chiamare EndInvoke() dopo altrimenti si può finire perdite di risorse

Vorrei anche essere tentati di mettere un pulsante annulla nella finestra di dialogo di avanzamento, e aggiungere un timeout, altrimenti se l'aggiornamento si blocca (o richiede troppo tempo), la vostra applicazione sarà bloccato per sempre.

Altri suggerimenti

Hai provato a mettere un

Application.DoEvents()

qui

if (dlgRes == DialogResult.Yes)
{
   Application.DoEvents(); 
   ProcessAllUpdates(um2); 
}

@ Giovanni Sibly

Si può ottenere via con non chiamata EndInvoke quando ha a che fare con WinForms, senza conseguenze negative.

L'unico documentato eccezione alla regola che io sappia è in Windows Form, dove si sono ufficialmente autorizzati al Controllo delle chiamate.BeginInvoke senza preoccuparsi di Controllo delle chiamate.EndInvoke.

Tuttavia, in tutti gli altri casi, quando si tratta con l'inizio/Fine Asincrono modello si deve presumere che avrà una perdita, come lei ha dichiarato.

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