如何显示“正在加载”。 。 。请稍候” Winforms 中针对长时间加载表单的消息?

发布于 2024-08-14 14:01:22 字数 114 浏览 11 评论 0原文

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

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

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

I have a form that is very slow because there are many controls placed on the form.

As a result the form takes a long time to loaded.

How do I load the form first, then display it and while loading delay show another form which that have message like "Loading... please wait.?"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

停顿的约定 2024-08-21 14:01:22

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

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

通过这种方式,您仅使用一个主 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();

Using a separate thread to display a simple please wait message is overkill especially if you don't have much experience with threading.

A much simpler approach is to create a "Please wait" form and display it as a mode-less window just before the slow loading form. Once the main form has finished loading, hide the please wait form.

In this way you are using just the one main UI thread to firstly display the please wait form and then load your main form.

The only limitation to this approach is that your please wait form cannot be animated (such as a animated GIF) because the thread is busy loading your main form.

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();
暮凉 2024-08-21 14:01:22

我查看了大多数发布的解决方案,但发现了我更喜欢的另一种解决方案。它很简单,不使用线程,并且可以满足我的需要。

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

I looked at most the solutions posted, but came across a different one that I prefer. It's simple, doesn't use threads, and works for what I want it to.

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

I added to the solution in the article and moved the code into a base class that all my forms inherit from. Now I just call one function: ShowWaitForm() during the frm_load() event of any form that needs a wait dialogue box while the form is loading. Here's the code:

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 is the name of a form you create to look like a wait dialogue. I added a SetMessage() function to customize the text on the wait form.

£冰雨忧蓝° 2024-08-21 14:01:22

您想查看“启动画面”。

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

这是一个关于如何执行此操作的示例

You want to look into 'Splash' Screens.

Display another 'Splash' form and wait until the processing is done.

Here is an example on how to do it.

☆獨立☆ 2024-08-21 14:01:22

一个简单的解决方案:

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

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

然后用“加载”代替“睡眠”。
这会故意阻塞 UI 线程。

A simple solution:

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

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

And then substitute your Loading for the Sleep.
This blocks the UI thread, on purpose.

小…楫夜泊 2024-08-21 14:01:22

使“加载屏幕”仅在特定时间显示的另一种方法是将其放在事件之前并在事件完成其工作后将其关闭。

例如:您想为将结果保存为 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 块。

Another way of making "Loading screen" only display at certain time is, put it before the event and dismiss it after event finished doing it's job.

For example: you want to display a loading form for an event of saving result as MS Excel file and dismiss it after finished processing, do as follows:

LoadingWindow loadingWindow = new LoadingWindow();

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

Or you can put loadingWindow.Close() inside finally block.

思慕 2024-08-21 14:01:22

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

You should create a background thread to to create and populate the form. This will allow your foreground thread to show the loading message.

伪装你 2024-08-21 14:01:22

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

I put some animated gif in a form called FormWait and then I called it as:

// 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();
夏夜暖风 2024-08-21 14:01:22

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

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

Well i do it some thing like this.

        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);
错爱 2024-08-21 14:01:22

你可以看一下我的闪屏实现:
C# winforms 启动(Splash)表单不隐藏

You can take a look at my splash screen implementation:
C# winforms startup (Splash) form not hiding

杀お生予夺 2024-08-21 14:01:22

当您还有动画图像时,最好的方法是:

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

The best approach when you also have an animated image is this one:

1- You have to create a "WaitForm" that receives the method that it will executed in background. Like this one

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 - You can use the Waitform like this

private void btnShowWait_Click(object sender, EventArgs e)
{
    new WaitForm(() => /*Simulate long task*/ Thread.Sleep(2000)).ShowDialog();
}
百合的盛世恋 2024-08-21 14:01:22

或者,如果您不想要任何花哨的东西,例如动画等,您可以创建一个标签并将其停靠到窗体中,然后将其 z-index 从文档大纲窗口更改为 0 并为其指定背景颜色,以便其他控件不会比 run < 可见code>Application.DoEvents() 一旦在表单加载事件中,并在表单显示事件中进行所有编码,并在显示事件中将标签可见属性设置为 false,然后运行 ​​Application.DoEvents()< /代码> 再次。

or if you don't want anything fancy like animation etc. you can create a label and dock it to form then change it's z-index from document outline window to 0 and give it a background color so other controls wont be visible than run Application.DoEvents() once in form load event and do all your coding in form shown event and at the and of shown event set your label visible property to false then run Application.DoEvents() again.

顾挽 2024-08-21 14:01:22

我知道已经很晚了,但我喜欢这个项目,我想与您分享,它非常有用且示例
WinForms中简单的等待显示对话框

I know it is wery late, but I fonded this project and I would like to share with you, it is very usefull and sample
Simple Display Dialog of Waiting in WinForms

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文