如何在Winforms中显示“正在加载...请等待”消息以获取长时间加载的表单?

时间:2009-12-16 22:11:57

标签: c# winforms

我有一个非常慢的表单,因为表单上放置了许多控件。

结果表单需要很长时间才能加载。

如何首先加载表单,然后显示它,并在加载延迟时显示另一个表单,其中包含“正在加载......请等待。”

12 个答案:

答案 0 :(得分:53)

使用单独的线程来显示简单的请等待消息是过度的,特别是如果您没有太多的线程经验。

更简单的方法是创建一个“请等待”表单,并在缓慢加载表单之前将其显示为无模式窗口。主表单完成加载后,隐藏请等待表单。

通过这种方式,您只使用一个主UI线程首先显示请等待表单,然后加载主表单。

此方法的唯一限制是您的请等待表单无法设置动画(例如动画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();

答案 1 :(得分:24)

我最常查看所发布的解决方案,但遇到了我更喜欢的另一个解决方案。它很简单,不使用线程,并且可以满足我的需求。

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

我在文章中添加了解决方案,并将代码移动到我的所有表单都继承自的基类中。现在我只是在表单加载时需要等待对话框的任何表单的frm_load()事件期间调用一个函数:ShowWaitForm()。这是代码:

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()函数来自定义等待表单上的文本。

答案 2 :(得分:18)

您想要查看'Splash'屏幕。

显示另一个'Splash'表单并等待处理完成。

以下是关于如何操作的快速而肮脏的post

这是一个更好的example

答案 3 :(得分:10)

另一种使“加载屏幕”仅在特定时间显示的方法是,在事件发生之前将其放置并在事件结束后将其解雇。

例如:您希望显示将结果保存为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阻止。

答案 4 :(得分:7)

一个简单的解决方案:

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

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

然后用你的装载代替睡眠 这会故意阻止UI线程。

答案 5 :(得分:5)

您应该创建一个后台线程来创建和填充表单。这将允许您的前台线程显示加载消息。

答案 6 :(得分:4)

您可以查看我的启动画面实现: C# winforms startup (Splash) form not hiding

答案 7 :(得分:3)

当您拥有动画图像时,最佳方法是:

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 - 您可以像这样使用Waitform

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

答案 8 :(得分:3)

我将一些动画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();

答案 9 :(得分:3)

我做这样的事情。

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();
 }

答案 10 :(得分:1)

或者,如果您不希望动画等任何花哨的东西,您可以创建一个标签并将其停靠形成表格,然后将其z-index从文档轮廓窗口更改为0并为其设置背景色,以便其他控件不可见而不是在表单加载事件中运行一次Application.DoEvents(),并在表单显示事件中进行所有编码,并在和显示事件中将标签的visible属性设置为false,然后再次运行Application.DoEvents()

答案 11 :(得分:0)

我知道现在很晚,但是我喜欢这个项目,并想与您分享,它非常有用并且非常有用 Simple Display Dialog of Waiting in WinForms