2009-12-16 32 views

Respuesta

46

El uso de un hilo separado para mostrar un simple favor espere mensaje es un exceso, especialmente si usted no tiene mucha experiencia con rosca.

Un enfoque mucho más simple es crear una forma "Por favor espere" y mostrarlo como una ventana de modo menos justo antes de que el formulario de carga lenta. Una vez que el formulario principal haya terminado de cargarse, oculte el formulario de espera por favor.

De esta manera se está utilizando sólo el hilo principal interfaz de usuario para mostrar la forma en primer lugar por favor espere y luego cargar el formulario principal.

La única limitación de este enfoque es que el formulario por favor espere no puede ser animado (como un GIF animado) porque el hilo está ocupado carga el formulario principal.

PleaseWaitForm pleaseWait=new PleaseWaitForm(); 

// Display form modelessly 
pleaseWait.Show(); 

// ALlow main UI thread to properly display please wait form. 
Application.DoEvents(); 

// Show or load the main form. 
mainForm.ShowDialog(); 
+0

manera de utilizar imágenes animadas en su acercamiento a la todavía animados? – Sadegh

+1

@Sadegh, necesitaría usar un control en su formulario de espera por favor que internamente crea un hilo para animar la imagen. No creo que el PictureBox estándar haga esto. Sin embargo, si definitivamente necesitas animación, vale la pena mirar algunas de las páginas vinculadas de David. – Ash

+5

Nunca use 'Application.DoEvents();'! –

15

Quiere ver las pantallas 'Splash'.

Muestre otro formulario 'Splash' y espere hasta que finalice el procesamiento.

Aquí es una rápida y sucia post sobre cómo hacerlo.

Aquí hay una mejor example.

4

Debe crear un hilo de fondo para crear y completar el formulario. Esto permitirá que su hilo en primer plano muestre el mensaje de carga.

+4

realmente no se puede crear y utilizar un formulario en Windows Forms en un subproceso de interfaz de usuario no existe .... –

5

Una solución simple:

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

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

Y luego sustituya su carga para el sueño.

21

Miré la mayoría de las soluciones publicadas, pero encontré una que yo prefiero. Es simple, no usa hilos, y funciona para lo que yo quiero.

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

I a la solución en el artículo y se trasladó el código en una clase base que todos mis formas heredan de. Ahora solo llamo a una función: ShowWaitForm() durante el evento frm_load() de cualquier formulario que necesite un cuadro de diálogo de espera mientras se carga el formulario. Aquí está el código:

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 es el nombre de una forma de crear para parecerse a un diálogo de espera. Agregué una función SetMessage() para personalizar el texto en el formulario de espera.

+0

dice que mywaitform no existe – CDrosos

+0

Encontré esto como un mejor enfoque, diseñé mi propia forma de espera y está 'funcionando bien ... – Bharat

8

Otra forma de hacer "Carga de pantalla" sólo se muestran en un momento determinado está, puesto que antes del evento y descartarla después del evento terminó haciendo su trabajo.

Por ejemplo: desea mostrar un formulario de carga para un evento de resultado el ahorro como archivo de MS Excel y descartarla después del procesamiento terminado, haga lo siguiente:

LoadingWindow loadingWindow = new LoadingWindow(); 

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

O usted puede poner loadingWindow.Close() dentro finally bloque .

+1

esto casi nunca funcionará. El subproceso en primer plano continúa exportando a ExcelFile donde está ocupado antes de que se muestre la ventana loading. – rune711

0

El mejor enfoque cuando también tiene una imagen animada es éste:

1- Hay que crear un "WaitForm" que recibe el método que se ejecuta en segundo plano. Al igual que éste

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 - Puede utilizar el Waitform como éste

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

pongo algunos gif animado en una forma llamada FormWait y luego lo llamé como:

// 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

Intenté usar esto, pero obtengo una excepción de cruce ilegal de subprocesos IO. Lo modifiqué haciéndolo "seguro para subprocesos". No es la mejor práctica, pero para una forma simple de espera es aceptable: Reemplazar f.Close() con f.Invocar (nuevo ThreadStart (delegar {f.Close();})); –

+0

Agregué una solución probada aquí: https://stackoverflow.com/questions/15769276/best-way-to-display-a-progress-form-while-a-method-is-executing-code/45406217# 45406217 – user2288580

0

Bueno, lo hago algo así.

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

Intenté algo como esto, pero hace que mi aplicación pierda enfoque cuando la abro desde un tipo de archivo vinculado en Explorer ... – Nyerguds

Cuestiones relacionadas