Как показать сообщение «Идет загрузка ... пожалуйста, подождите» в Winforms для длинной формы загрузки? - PullRequest
42 голосов
/ 17 декабря 2009

У меня очень медленная форма, потому что в ней много элементов управления.

В результате форма загружается очень долго.

Как сначала загрузить форму, затем отобразить ее, а во время задержки загрузки показать другую форму с сообщением типа "Загрузка ... пожалуйста, подождите .?"

Ответы [ 12 ]

53 голосов
/ 17 декабря 2009

Использование отдельного потока для отображения простого сообщения, пожалуйста, подождите, излишне, особенно если у вас нет большого опыта работы с потоками.

Гораздо более простой подход - создать форму «Пожалуйста, подождите» и отобразить ее как окно без режима непосредственно перед формой медленной загрузки. Как только основная форма закончила загрузку, скройте, пожалуйста, форму ожидания.

Таким образом, вы используете только один основной поток пользовательского интерфейса, чтобы сначала отобразить форму ожидания, а затем загрузить основную форму.

Единственным ограничением этого подхода является то, что ваша форма ожидания не может быть анимирована (например, анимированный GIF), потому что поток занят загрузкой вашей основной формы.

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();
24 голосов
/ 31 января 2012

Я посмотрел большинство опубликованных решений, но наткнулся на другое, которое я предпочитаю. Это просто, не использует потоки и работает так, как я хочу.

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

Я добавил решение в статье и переместил код в базовый класс, от которого наследуются все мои формы. Теперь я просто вызываю одну функцию: ShowWaitForm () во время события frm_load () любой формы, для которой требуется диалоговое окно ожидания во время загрузки формы. Вот код:

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 - это имя формы, которую вы создаете, чтобы выглядеть как диалог ожидания. Я добавил функцию SetMessage () для настройки текста в форме ожидания.

18 голосов
/ 17 декабря 2009

Вы хотите посмотреть на экраны-заставки.

Отобразите еще одну форму «Всплеск» и дождитесь окончания обработки.

Вот быстрый и грязный пост о том, как это сделать.

Вот лучший пример .

10 голосов
/ 08 марта 2012

Другой способ отображения «экрана загрузки» только в определенное время - поместить его перед событием и закрыть после того, как событие завершило свою работу.

Например: вы хотите отобразить форму загрузки для события сохранения результата в виде файла MS Excel и закрыть его после завершения обработки, выполните следующие действия:

LoadingWindow loadingWindow = new LoadingWindow();

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

Или вы можете поместить loadingWindow.Close() внутрь finally блока.

7 голосов
/ 17 декабря 2009

Простое решение:

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

    System.Threading.Thread.Sleep(2500);
} // f2 is closed and disposed here

А затем замените свою Загрузка на Сон.
Это блокирует поток пользовательского интерфейса, специально.

5 голосов
/ 17 декабря 2009

Вы должны создать фоновый поток, чтобы создать и заполнить форму. Это позволит вашей основной теме показывать сообщение о загрузке.

4 голосов
/ 02 октября 2017

Ну, я делаю что-то вроде этого.

NormalWaitDialog/*your wait form*/ _frmWaitDialog = null;

//For static wait dialog
//On an Event
_frmWaitDialog = new NormalWaitDialog();
_frmWaitDialog.Shown += async (s, e) =>
{
   Refresh();
   await Task.Run(() =>
   {
      //Do your stuff
   });
_frmWaitDialog.Close();
};
_frmWaitDialog.ShowDialog(this);



//For animated wait dialog
//On an event
_frmWaitDialog = new NormalWaitDialog();
_frmWaitDialog.Shown += (s, e) =>
{
   //create a async method and call the method here
   LoadDataAsync();
};
_frmWaitDialog.ShowDialog(this);

 //Async Method
 private async void LoadDataAsync(){
       await Task.Run(() =>
       {
          //Do your stuff
       });
       _frmWaitDialog.Close();
 }
4 голосов
/ 17 декабря 2009

Вы можете взглянуть на мою реализацию заставки: C # winforms запуска (Splash) форма не скрывается

3 голосов
/ 31 октября 2016

Я поместил анимированный GIF-файл в форму с именем FormWait, а затем назвал ее:

// 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();
3 голосов
/ 18 августа 2016

Лучший подход, когда у вас есть анимированное изображение, это:

1 - Вы должны создать «WaitForm», который получает метод, который будет выполняться в фоновом режиме. Как этот

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 - Вы можете использовать форму ожидания следующим образом

private void btnShowWait_Click(object sender, EventArgs e)
{
    new WaitForm(() => /*Simulate long task*/ Thread.Sleep(2000)).ShowDialog();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...