我有一个表单,因为在表单上放置了许多控件,所以非常缓慢。
因此表单加载需要很长时间。
如何先加载表单,然后显示它,在加载过程中显示另一个带有消息"正在加载,请稍候"的表单?
如果你对线程没有太多经验,那么使用一个单独的线程来显示简单的“请等待”消息就有些过度了。
一种更简单的方法是创建一个“请等待”表单,并将它作为一个无模态窗口显示在慢加载表单之前。一旦主表单加载完成,就隐藏“请等待”表单。
通过这种方式,你只使用一个主 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();
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
然后将您的加载替换为睡眠。
这是有意阻塞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
块中。
我在一个名为FormWait
的表单中放置了一些动画gif,然后我这样调用它:
// 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
// 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);
.ConfigureAwait(true)
是默认值。 - Panagiotis Kanavos您应该创建一个后台线程来创建和填充表单。这将允许您的前台线程显示加载消息。
当您同时拥有一个动画图像时,最好的方法是:
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();
}
Application.DoEvents();
! - CodeTherapist