与
相似MessageBox.Show("Test", "Test")
我制作了一个ProgressWindow,它在长时间运行之前显示,然后隐藏:
ProgressWindow.Show("Test","Test")
Thread.Sleep(20000);
ProgressWindow.Hide();
使用以下代码:
class ProgressWindow : Form
{
private Label label1;
private static ProgressWindow window;
internal static void Show(string Message, string Caption)
{
window = new ProgressWindow(Message, Caption);
window.Show();
}
internal new static void Hide()
{
(ProgressWindow.window as Control).Hide();
}
private ProgressWindow(string Message, string Caption)
{
InitializeComponent(Message, Caption);
}
private void InitializeComponent(string Message, string Caption)
{
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.Location = new System.Drawing.Point(50, 40);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(300, 120);
this.label1.TabIndex = 0;
this.label1.Text = Message;
//
// ProgressWindow
//
this.ClientSize = new System.Drawing.Size(400, 200);
this.ShowIcon = false;
this.MinimizeBox = false;
this.MaximizeBox = false;
this.ControlBox = false;
this.FormBorderStyle = FormBorderStyle.FixedDialog;
this.StartPosition = FormStartPosition.CenterScreen;
this.Controls.Add(this.label1);
this.Name = "ProgressWindow";
this.Text = Caption;
this.TopMost = true;
this.ResumeLayout(false);
}
}
现在的问题是显示了我的进度窗口,但是在标签的位置,只有一个白色的盒子,没有文字。此外,如果我尝试单击该窗口,标题将从"测试"到"测试(没有回复...)"。
为什么会这样,我将如何改变它?
我怀疑线程阻塞有问题(但为什么?不应该渲染标签?)并尝试
internal static void Show(string Message, string Caption)
{
window = new ProgressWindow(Message, Caption);
new Thread(t => {
window.Show();
}).Start();
}
但这根本不显示ProgressWindow表单。
答案 0 :(得分:0)
是的,问题是由于线程阻塞造成的。调用Thread.Sleep()
时,当前线程无效,这意味着不处理任何Windows消息。这可以防止您的进度对话框完全显示其UI。
我不确定为什么在后台线程上调用Show()
方法不起作用,但我相信WinForms要求UI线程是一个单线程公寓,默认情况下线程是Multi-螺纹公寓。
为了正确实现这一点,我建议使用BackgroundWorker类。它会自动创建一个后台线程来执行长时间运行的工作,并在工作完成后触发一次。您可以使用以下内容:
ProgressWindow.Show("Test","Test");
var worker = new BackgroundWorker();
worker.DoWork += (sender, args) => {
// perform your long running task here, this is a background thread
Thread.Sleep(2000);
};
worker.RunWorkerCompleted += (sender, args) => {
// update the UI here, this is running on the UI thread
ProgressWindow.Hide();
}
worker.RunWorkerAsync();
请注意,RunWorkerAsync()
会立即返回,因此您的UI需要处理用户在后台任务完成之前可以与UI进行交互的事实。