2009-12-16 18 views

risposta

46

Utilizzando un thread separato per visualizzare un semplice Attendere messaggio è eccessivo, soprattutto se non si ha molta esperienza con filettatura.

Un approccio molto più semplice consiste nel creare un modulo "Attendere prego" e visualizzarlo come una finestra di modalità prima del caricamento lento. Una volta completato il caricamento del modulo principale, nascondi il modulo di attesa.

In questo modo si utilizza solo il thread principale dell'interfaccia utente per visualizzare innanzitutto il modulo di attesa, quindi caricare il modulo principale.

L'unica limitazione a questo approccio è che il modulo di attesa in attesa non può essere animato (ad esempio una GIF animata) perché il thread è occupato durante il caricamento del modulo principale.

+0

esiste modo per utilizzare le immagini animate nel vostro approccio alla animato ancora? – Sadegh

+1

@Sadegh, dovresti usare un controllo sul tuo modulo di attesa per favore che crea internamente un thread per animare l'immagine. Non penso che PictureBox standard lo faccia. Tuttavia, se hai sicuramente bisogno di animazione, vale la pena guardare alcune delle pagine collegate a David. – Ash

+5

Non usare mai 'Application.DoEvents();'! –

15

Si desidera esaminare le schermate di 'Splash'.

Visualizzare un altro modulo "Splash" e attendere fino al termine dell'elaborazione.

Ecco un veloce e sporco post su come farlo.

Ecco un migliore example.

4

È necessario creare un thread in background per creare e compilare il modulo. Ciò consentirà al thread in primo piano di mostrare il messaggio di caricamento.

+4

non si può davvero creare e utilizzare un modulo in Windows Form in un thread non-UI .... –

5

Una soluzione semplice:

using (Form2 f2 = new Form2()) 
{ 
    f2.Show(); 
    f2.Update(); 

    System.Threading.Thread.Sleep(2500); 
} 

E poi sostituire il carico per il sonno.

21

Ho guardato al massimo le soluzioni pubblicate, ma ne ho trovato uno diverso che preferisco. È semplice, non usa thread e funziona per quello che voglio.

http://weblogs.asp.net/kennykerr/archive/2004/11/26/where-is-form-s-loaded-event.aspx

ho aggiunto alla soluzione in questo articolo e si è trasferito il codice in una classe base che tutte le mie forme ereditano da. Ora chiamo una funzione: ShowWaitForm() durante l'evento frm_load() di qualsiasi modulo che necessita di una finestra di dialogo di attesa mentre il modulo viene caricato. Ecco il codice:

public class MyFormBase : System.Windows.Forms.Form 
{ 
    private MyWaitForm _waitForm; 

    protected void ShowWaitForm(string message) 
    { 
     // don't display more than one wait form at a time 
     if (_waitForm != null && !_waitForm.IsDisposed) 
     { 
      return; 
     } 

     _waitForm = new MyWaitForm(); 
     _waitForm.SetMessage(message); // "Loading data. Please wait..." 
     _waitForm.TopMost = true; 
     _waitForm.StartPosition = FormStartPosition.CenterScreen; 
     _waitForm.Show(); 
     _waitForm.Refresh(); 

     // force the wait window to display for at least 700ms so it doesn't just flash on the screen 
     System.Threading.Thread.Sleep(700);   
     Application.Idle += OnLoaded; 
    } 

    private void OnLoaded(object sender, EventArgs e) 
    { 
     Application.Idle -= OnLoaded; 
     _waitForm.Close(); 
    } 
} 

MyWaitForm è il nome di un modulo si crea per assomigliare ad un dialogo di attesa. Ho aggiunto una funzione SetMessage() per personalizzare il testo sul modulo di attesa.

+0

dice che mywaitform non esiste – CDrosos

+0

Ho trovato questo come un approccio migliore, ho progettato il mio modulo di attesa e funziona bene ... – Bharat

8

Un altro modo per rendere la "schermata di caricamento" visualizzata solo in un determinato momento è metterlo prima dell'evento e chiuderlo dopo che l'evento è terminato, facendo il suo lavoro.

Per esempio: si desidera visualizzare un modulo di carico per un evento di conseguenza salvare come file di MS Excel e respingerlo dopo la lavorazione finita, procedere come segue:

LoadingWindow loadingWindow = new LoadingWindow(); 

try 
{ 
    loadingWindow.Show();     
    this.exportToExcelfile(); 
    loadingWindow.Close(); 
} 
catch (Exception ex) 
{ 
    MessageBox.Show("Exception EXPORT: " + ex.Message); 
} 

Oppure si può mettere loadingWindow.Close() all'interno finally blocco .

+1

questo quasi mai funzionerà. Il thread in primo piano continua ad esportare su Excel file dove è occupato prima che venga visualizzata la finestra di caricamento. – rune711

0

L'approccio migliore quando si ha anche un'immagine animata è questo:

1- È necessario creare un "WaitForm" che riceve il metodo che sarà eseguito in background. Come questo

public partial class WaitForm : Form 
{ 
    private readonly MethodInvoker method; 

    public WaitForm(MethodInvoker action) 
    { 
     InitializeComponent(); 
     method = action; 
    } 

    private void WaitForm_Load(object sender, EventArgs e) 
    { 
     new Thread(() => 
     { 
      method.Invoke(); 
      InvokeAction(this, Dispose); 
     }).Start(); 
    } 

    public static void InvokeAction(Control control, MethodInvoker action) 
    { 
     if (control.InvokeRequired) 
     { 
      control.BeginInvoke(action); 
     } 
     else 
     { 
      action(); 
     } 
    } 
} 

2 - È possibile utilizzare il Waitform come questo

private void btnShowWait_Click(object sender, EventArgs e) 
{ 
    new WaitForm(() => /*Simulate long task*/ Thread.Sleep(2000)).ShowDialog(); 
} 
1

ho messo un po 'di gif animate in una forma chiamata FormWait e poi ho chiamato come:

// show the form 
new Thread(() => new FormWait().ShowDialog()).Start(); 

// do the heavy stuff here 

// get the form reference back and close it 
FormWait f = new FormWait(); 
f = (FormWait)Application.OpenForms["FormWait"]; 
f.Close(); 
+1

Ho provato a utilizzare questo, ma ottengo un'eccezione di attraversamento di thread illegali IO. L'ho modificato rendendolo "thread-safe". Non è la migliore pratica, ma per un semplice modulo di attesa è accettabile: Sostituisci f.Close() con f.Invoke (new ThreadStart (delegate {f.Close();})); –

+0

Ho aggiunto una soluzione testata qui: https://stackoverflow.com/questions/15769276/best-way-to-display-a-progress-form-while-a-method-is-executing-code/45406217# 45406217 – user2288580

0

Beh, lo faccio qualcosa del genere.

DataTable SLTable = new DataTable(); 
_frmWaitDialog = new NormalWaitDialog(); 
_frmWaitDialog.Shown += async (s, e) => 
{ 
    Refresh(); 
    await Task.Run(() => 
    { 
     //Do your stuff 
    }); 
_frmWaitDialog.Close(); 
}; 
_frmWaitDialog.ShowDialog(this); 
+0

Ho provato qualcosa di simile, ma fa sì che la mia app perda messa a fuoco quando la apro da un tipo di file collegato in Explorer ... – Nyerguds

Problemi correlati