【发布时间】:2010-12-27 10:50:14
【问题描述】:
我有一个非常慢的表单,因为表单上放置了许多控件。
因此,表单需要很长时间才能加载。
如何先加载表单,然后显示它,并在加载延迟时显示另一个表单,其中包含“正在加载...请稍候。”之类的消息?
【问题讨论】:
标签: c# .net winforms .net-core
我有一个非常慢的表单,因为表单上放置了许多控件。
因此,表单需要很长时间才能加载。
如何先加载表单,然后显示它,并在加载延迟时显示另一个表单,其中包含“正在加载...请稍候。”之类的消息?
【问题讨论】:
标签: c# .net winforms .net-core
使用单独的线程来显示一个简单的请稍候消息是矫枉过正的,尤其是如果您对线程没有太多经验。
一个更简单的方法是创建一个“请稍候”表单并将其显示为一个无模式窗口,就在缓慢加载表单之前。主表单加载完成后,隐藏请等待表单。
通过这种方式,您只使用一个主 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();
【讨论】:
Application.DoEvents();!
我查看了大多数发布的解决方案,但发现了一个我更喜欢的不同解决方案。它很简单,不使用线程,并且可以满足我的需求。
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() 函数来自定义等待表单上的文本。
【讨论】:
【讨论】:
一个简单的解决方案:
using (Form2 f2 = new Form2())
{
f2.Show();
f2.Update();
System.Threading.Thread.Sleep(2500);
} // f2 is closed and disposed here
然后用 Loading 代替 Sleep。
这会故意阻塞 UI 线程。
【讨论】:
另一种使“加载屏幕”仅在特定时间显示的方法是将其放在事件之前并在事件完成后将其关闭。
例如:您想显示一个将结果保存为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 块内。
【讨论】:
您应该创建一个后台线程来创建和填充表单。这将允许您的前台线程显示加载消息。
【讨论】:
你可以看看我的启动画面实现: C# winforms startup (Splash) form not hiding
【讨论】:
我将一些动画 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);
【讨论】:
.ConfigureAwait(true) 是默认值
当您还拥有动画图像时,最好的方法是:
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();
}
【讨论】:
或者如果您不想要动画等花哨的东西。您可以创建一个标签并将其停靠在窗体上,然后将其 z-index 从文档大纲窗口更改为 0 并为其设置背景色,以便其他控件不可见比在表单加载事件中运行一次Application.DoEvents() 并在表单显示事件中进行所有编码,并在显示事件的 and 中将标签可见属性设置为 false,然后再次运行 Application.DoEvents()。
【讨论】:
我知道已经晚了,但我喜欢这个项目,我想和你分享,它非常有用和样本 Simple Display Dialog of Waiting in WinForms
【讨论】: