我有以下WaitScreen类在执行后台进程时显示“请稍候...”消息:
public class WaitScreen
{
// Fields
private object lockObject = new object();
private string message = "Please Wait...";
private Form waitScreen;
// Methods
public void Close()
{
lock (this.lockObject)
{
if (this.IsShowing)
{
try
{
this.waitScreen.Invoke(new MethodInvoker(this.CloseWindow));
}
catch (NullReferenceException)
{
}
this.waitScreen = null;
}
}
}
private void CloseWindow()
{
this.waitScreen.Dispose();
}
public void Show(string message)
{
if (this.IsShowing)
{
this.Close();
}
if (!string.IsNullOrEmpty(message))
{
this.message = message;
}
using (ManualResetEvent event2 = new ManualResetEvent(false))
{
Thread thread = new Thread(new ParameterizedThreadStart(this.ThreadStart));
thread.SetApartmentState(ApartmentState.STA);
thread.Start(event2);
event2.WaitOne();
}
}
private void ThreadStart(object parameter)
{
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
ManualResetEvent event2 = (ManualResetEvent)parameter;
Application.EnableVisualStyles();
this.waitScreen = new Form();
this.waitScreen.Tag = event2;
this.waitScreen.ShowIcon = false;
this.waitScreen.ShowInTaskbar = false;
this.waitScreen.AutoSize = true;
this.waitScreen.AutoSizeMode = AutoSizeMode.GrowAndShrink;
this.waitScreen.BackColor = SystemColors.Window;
this.waitScreen.ControlBox = false;
this.waitScreen.FormBorderStyle = FormBorderStyle.FixedToolWindow;
this.waitScreen.StartPosition = FormStartPosition.CenterScreen;
this.waitScreen.Cursor = Cursors.WaitCursor;
this.waitScreen.Text = "";
this.waitScreen.FormClosing += new FormClosingEventHandler(this.WaitScreenClosing);
this.waitScreen.Shown += new EventHandler(this.WaitScreenShown);
Label label = new Label();
label.Text = this.message;
label.AutoSize = true;
label.Padding = new Padding(20, 40, 20, 30);
this.waitScreen.Controls.Add(label);
Application.Run(this.waitScreen);
Application.ExitThread();
}
private void WaitScreenClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
}
}
private void WaitScreenShown(object sender, EventArgs e)
{
Form form = (Form)sender;
form.Shown -= new EventHandler(this.WaitScreenShown);
ManualResetEvent tag = (ManualResetEvent)form.Tag;
form.Tag = null;
tag.Set();
}
// Properties
public bool IsShowing
{
get
{
return (this.waitScreen != null);
}
}
}
我使用它的方式是:
waitScreen = new WaitScreen();
waitScreen.Show("Please wait...");
我有一个MainForm,在mainform中我有一个按钮,当点击时我会显示一个Dialog,在加载时会从Backgroundworker中的数据库中获取一些数据。在运行backgroundworker之前,我会显示 WaitScreen 。
它工作得很好但是当显示 WaitScreen 时如果我点击后面的对话框,那么 WaitScreen 就消失了。所以我想阻止,所以我不能点击后面的对话框,直到工人完成,然后我关闭 WaitScreen 。
有关如何做到这一点的任何线索?
非常感谢。
答案 0 :(得分:1)
我认为你过于复杂了。你想要的是一个模态对话窗口,用户无法关闭,当给定任务完成时,该窗口将关闭。
您可以创建一个派生自Form
的标准类,并实现可以传递Task或回调的构造函数或属性。
以下是您的WaitScreen
表单中的代码:
public partial class WaitScreen : Form
{
public Action Worker { get; set; }
public WaitScreen(Action worker)
{
InitializeComponent();
if (worker == null)
throw new ArgumentNullException();
Worker = worker;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Task.Factory.StartNew(Worker).ContinueWith(t => { this.Close(); }, TaskScheduler.FromCurrentSynchronizationContext());
}
}
以下是您的代码在此WaitScreen
表单的使用者中的样子:
private void someButton_Click(object sender, EventArgs e)
{
using (var waitScreen = new WaitScreen(SomeWorker))
waitScreen.ShowDialog(this);
}
private void SomeWorker()
{
// Load stuff from the database and store it in local variables.
// Remember, this is running on a background thread and not the UI thread, don't touch controls.
}
您可能希望在WaitScreen中使用FormBorderStyle.None,以便用户无法关闭它。然后任务完成,WaitScreen将自行关闭,调用者将在ShowDialog()
调用后继续执行代码。 ShowDialog()
阻止调用线程。