C# 我如何显示“a”;加载。请稍等;长加载窗体的Winforms中的消息?

C# 我如何显示“a”;加载。请稍等;长加载窗体的Winforms中的消息?,c#,.net,winforms,.net-core,C#,.net,Winforms,.net Core,我有一个非常慢的表单,因为表单上放置了许多控件 因此,加载表单需要很长时间 如何首先加载表单,然后显示它,并在加载延迟时显示另一个表单,其中包含“正在加载…请稍候”之类的消息?“您想查看“启动”屏幕 显示另一个“Splash”表单并等待处理完成 下面是一个关于如何操作的示例。您应该创建一个后台线程来创建和填充表单。这将允许前台线程显示加载消息。一个简单的解决方案: using (Form2 f2 = new Form2()) { f2.Show(); f2.Update();

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

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


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

您想查看“启动”屏幕

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


下面是一个关于如何操作的示例。

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

一个简单的解决方案:

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

    System.Threading.Thread.Sleep(2500);
} // f2 is closed and disposed here
然后用负载代替睡眠。

这会故意阻止UI线程

您可以查看我的启动屏幕实现:

使用单独的线程来显示简单的“请稍候”消息是过分的,尤其是在您没有太多线程经验的情况下

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

这样,您只需使用一个主UI线程,即可首先显示请等待表单,然后加载主表单

这种方法的唯一限制是,由于线程正忙于加载主窗体,因此无法为please wait窗体设置动画(如动画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();

我查看了大多数发布的解决方案,但发现了另一个我更喜欢的解决方案。它很简单,不使用线程,并为我想要的工作

我在文章中添加了解决方案,并将代码移动到一个基类中,我的所有表单都从该基类继承。现在,我只需调用一个函数: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()函数来自定义等待表单上的文本。

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

例如:要将结果另存为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
块中。

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

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

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

我是这样做的

        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 

               //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);
NormalWaitDialog/*您的等待表单*/\u frmWaitDialog=null;
//Btn加载点击事件
_frmWaitDialog=新建NormalWaitDialog();
_frmWaitDialog.Showed+=async(s,ee)=>
{
等待任务。运行(()=>
{
//在这里做你的事
//制作长时间运行的循环以模拟长时间的过程
int x=0;
对于(int i=0;i
或者,如果您不想要动画等花哨的东西,您可以创建一个标签并将其固定到表单中,然后将其z索引从文档大纲窗口更改为0,并为其提供背景色,以便在运行
Application.DoEvents()之后,其他控件不可见
在form load事件中执行一次,然后在form Showed事件中执行所有编码,并在显示事件的和处将label visible属性设置为false,然后再次运行
Application.DoEvents()

我知道已经很晚了,但我喜欢这个项目,我想与您分享,它非常有用,非常简单

exist在处理静态动画时使用动画图像的方法?@Sadegh,您需要在请等待表单上使用一个控件,该控件在内部创建一个线程来设置图像动画。我不认为标准的PictureBox能做到这一点。但是,如果您确实需要动画,那么David的一些链接页面值得一看@C Sharper,你的评论一定被截断了,而且“不适当”一词从结尾就消失了。从没想过这样做,节省了我很多时间。工作完美无瑕。谢谢这几乎是行不通的。在加载窗口显示之前,前台线程将继续导出到其繁忙的外部文件。我尝试使用此方法,但遇到IO非法线程交叉异常。我修改了它,使它“线程安全”。这不是最佳实践,但对于简单的等待表单,它是可以接受的:将f.Close()替换为f.Invoke(newthreadstart(委托{f.Close();}));我在这里添加了一个经过测试的解决方案:它说mywaitform不存在。我发现这是一个最好的方法,我设计了自己的等待表单,它工作得很好。在等待表单打开时在屏幕上放置静态图像或文本是一个很好的主意。我将调用更改为ShowWaitForm,并将其放在基类中。然后,我在基类中添加了一个布尔属性,这样我就可以设置该属性,它将加载wait表单。真棒的解决方案!我尝试过类似的方法,但当我在Explorer中从链接文件类型打开应用程序时,它会使我的应用程序失去焦点…效果很好。谢谢+1我喜欢这个简单的解决方案。是的,它对动画GIF不起作用,但我刚刚在对话框上贴了一个沙漏的图像,我很乐意。嗨,大卫,链接给出了404