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

Sad*_*egh 43 c# winforms

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

因此,表单需要很长时间才能加载.

如何首先加载表单,然后显示它,并在加载延迟时显示另一个表单,其中包含"正在加载......请等待.?"的消息.

Ash*_*Ash 57

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

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

通过这种方式,您只使用一个主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();
Run Code Online (Sandbox Code Playgroud)

  • @C Sharper,你的评论必须被截断,并且"不恰当"这个词从最后丢失了. (30认同)
  • 永远不要使用`Application.DoEvents();`! (6认同)

gok*_*ter 25

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

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

MyWaitForm是您创建的表单的名称,看起来像等待对话.我添加了一个SetMessage()函数来自定义等待表单上的文本.


Dav*_*rab 18

你想看看'Splash'屏幕.

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

这是一篇关于如何做的快速而肮脏的帖子.

这是一个更好的例子.


ahm*_*ziF 10

使"加载屏幕"仅在特定时间显示的另一种方式是,将其放在事件之前,并在事件完成之后将其解雇.

例如:您要为MS Excel文件显示保存结果的事件的加载表单,并在完成处理后将其关闭,请执行以下操作:

LoadingWindow loadingWindow = new LoadingWindow();

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

或者你可以放在loadingWindow.Close()内部finally.


Hen*_*man 7

简单的解决方案:

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

    System.Threading.Thread.Sleep(2500);
} // f2 is closed and disposed here
Run Code Online (Sandbox Code Playgroud)

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


unh*_*ler 5

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

  • 您无法在非UI线程中的Windows窗体中创建和使用表单.... (5认同)

Dan*_*tti 5

我将一些动画 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();
Run Code Online (Sandbox Code Playgroud)

  • 我尝试使用这个,但我得到一个 IO 非法线程交叉异常。我通过使其成为“线程安全”来修改它。这不是最佳实践,但对于简单的等待形式是可以接受的:将 f.Close() 替换为 f.Invoke(new ThreadStart(delegate {f.Close();})); (3认同)

Muh*_*ziz 5

好吧,我做了这样的事情。

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


        //Btn Load Click Event
        _frmWaitDialog = new NormalWaitDialog();
        _frmWaitDialog.Shown += async (s, ee) =>
        {
            await Task.Run(() =>
           {
               // DO YOUR STUFF HERE 
               // And if you want to access the form controls you can do it like this
               this.Invoke(new Action(() =>
               {
                   //here you can access any control of form you want to access from cross thread! example
                   TextBox1.Text = "Any thing!";
               }));

               //Made long running loop to imitate lengthy process
               int x = 0;
               for (int i = 0; i < int.MaxValue; i++)
               {
                   x += i;
               }

           }).ConfigureAwait(true);
            _frmWaitDialog.Close();
        };
        _frmWaitDialog.ShowDialog(this);
Run Code Online (Sandbox Code Playgroud)