我基本上需要向用户显示一个等待窗口。为此,我在应用程序中放置了两个单独的窗口表单。第一个表单是带有按钮的主窗体。第二个是空的,只有一个标签文本。单击Form1中的按钮,我执行以下操作
Form2 f = new Form2();
f.Show();
Thread.Sleep(2000);
f.Close();
我的想法是向用户显示等待窗口2秒钟。但是当我这样做时,表格2没有完全加载,因为其中的标签是空白的。请告诉我你的意见。
答案 0 :(得分:3)
那是因为你可能在同一个线程(UI线程)中做了一些冗长的操作。您应该在新线程中执行代码(请参阅Thread类)或至少从冗长的操作中定期调用Application.DoEvents来更新UI。
答案 1 :(得分:3)
这是我使用的Waiting Box类。以下是您使用它的方式:
using WaitingBox;
ShowWaitingBox waiting = new ShowWaitingBox("Title Text","Some Text so the user knows whats going on..");
waiting.Start();
//do something that takes a while
waiting.Stop();
以下是WaitingBox的代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WaitingBox
{
public class ShowWaitingBox
{
private class WaitingForm:Form
{
public WaitingForm()
{
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.label1 = new System.Windows.Forms.Label();
this.progressBar1 = new System.Windows.Forms.ProgressBar();
this.tableLayoutPanel1.SuspendLayout();
this.SuspendLayout();
//
// tableLayoutPanel1
//
this.tableLayoutPanel1.ColumnCount = 1;
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel1.Controls.Add(this.progressBar1, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.label1, 0, 2);
this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 3;
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 29F));
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.tableLayoutPanel1.Size = new System.Drawing.Size(492, 155);
this.tableLayoutPanel1.TabIndex = 0;
//
// label1
//
this.label1.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(209, 92);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(73, 13);
this.label1.TabIndex = 3;
this.label1.Text = "Please Wait...";
//
// progressBar1
//
this.progressBar1.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
this.progressBar1.Location = new System.Drawing.Point(22, 37);
this.progressBar1.Name = "progressBar1";
this.progressBar1.Size = new System.Drawing.Size(447, 23);
this.progressBar1.TabIndex = 2;
//
// WaitingForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(492, 155);
this.Controls.Add(this.tableLayoutPanel1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Name = "WaitingForm";
this.Text = "Working in the background";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.WaitingForm_FormClosing);
this.Load += new System.EventHandler(this.WaitingForm_Load);
this.tableLayoutPanel1.ResumeLayout(false);
this.tableLayoutPanel1.PerformLayout();
this.ResumeLayout(false);
}
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
private System.Windows.Forms.ProgressBar progressBar1;
private System.Windows.Forms.Label label1;
private void WaitingForm_Load(object sender, EventArgs e)
{
progressBar1.Style = ProgressBarStyle.Marquee;
this.BringToFront();
this.CenterToScreen();
}
private void WaitingForm_FormClosing(object sender, FormClosingEventArgs e)
{
}
internal void SetLabel(string p)
{
label1.Text = p;
}
}
private WaitingForm wf = new WaitingForm();
private string title, text;
private Thread waiting;
public bool IsAlive
{
get
{
return waiting.IsAlive;
}
set { }
}
public ShowWaitingBox(string Title, string Text)
{
this.title = string.IsNullOrEmpty(Title) ? "Working in the Background..": Title;
this.text = string.IsNullOrEmpty(Text) ? "Please wait..." : Text;
waiting = new Thread(new ThreadStart(Show));
}
public ShowWaitingBox()
{
waiting = new Thread(new ThreadStart(Show));
}
private void Show()
{
wf.Show();
wf.Text = this.title;
wf.SetLabel(this.text);
while (true) {
wf.Refresh();
System.Threading.Thread.Sleep(50);
}
}
public void Start()
{
waiting.Start();
}
public void Stop()
{
waiting.Abort();
}
}
}
答案 2 :(得分:2)
当您使用Thread.Sleep时,您将禁用Windows消息循环并阻止窗口自行绘制。
你可以强制重画:
f.Refresh();
或者更好的是使用带回调的计时器。
Timer t = new Timer();
t.Interval = 2000;
t.Tick += delegate { Close(); t.Stop();};
t.Start();
要阻止用户点击原始窗口,您可以将新表单作为对话框打开:
f.ShowDialog();
答案 3 :(得分:1)
你基本上阻止了UI线程。
我建议您使用Form2构造函数(或可能的Load事件处理程序)启动一个计时器,该计时器将在两秒后触发。当计时器触发时,关闭表格。在这两秒钟内,UI线程将是空闲的,因此一切都将正常显示,用户将能够移动窗口等。
答案 4 :(得分:0)
我认为你应该使用
f.ShowDialog(this);
然后当f关闭时返回控制权。
通过使用sleep,您阻止UI线程更新2秒。 (线程处于休眠状态。)
答案 5 :(得分:-1)
你可以(对于UI线程总是应该)使用Thread.Current.Join(2000)而不是Thread.Sleep(2000)。