我设置了一个WinForm和一个循环过程,直到按下表单上的按钮为止。
当我尝试运行我的代码时,窗体甚至不显示。我怀疑这是因为代码被困在循环中,并且不足以显示WinForm。怎样才能让窗体显示出来,让循环在那个点之后运行呢?
发布于 2010-05-26 19:31:42
如果您因为在等待输入时需要定期处理图形用户界面而导致循环,我建议您使用Timer
control及其Tick
event。
如果你想在等待的时候做一些非图形用户界面的事情,more traditional timer更适合这个任务,
发布于 2010-05-26 19:35:06
您可能应该在后台线程中运行循环。BackgroundWorker类使得这项工作变得非常容易。
发布于 2010-05-26 19:33:06
窗体加载冻结,因为windows窗体的UI在单个线程中运行。您放在此窗体的Load事件上的逻辑正在该线程上运行。
通过在windows窗体上使用BackgroundWorker component,可以轻松地在单独的线程上运行循环。在后台worker的event DoWork中,您放置了应该在不阻塞UI的情况下运行的循环的代码。在Form.Load事件中,您可以通过调用方法RunWorkerAsync来启动后台工作程序组件。在按钮的事件处理程序上,通过调用CancelAsync method放置代码以停止后台工作程序。
文章How to: Implement a Form That Uses a Background Operation准确地展示了如何实现这一点。
关于您关于无法从后台工作程序组件更新TextBox文本的评论。发生这种情况是因为不允许从另一个线程修改windows窗体控件的状态(您的后台辅助代码在单独的线程上运行) MSDN文档说:
对Windows Forms控件的
访问本身不是线程安全的。如果有两个或更多线程操作控件的状态,则可能会强制该控件进入不一致的状态。其他线程相关的bug也是可能的,比如争用条件和死锁。确保以线程安全的方式执行对控件的访问非常重要。
如何从后台线程更新windows窗体控件的状态的示例与下面的示例类似(假设新值已经存储在名为text的字符串变量中):
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text = text;
}
我借用了How to: Make Thread-Safe Calls to Windows Forms Controls文章中的这段代码。它可以为您提供有关如何处理多线程windows窗体的更多信息。
https://stackoverflow.com/questions/2916096
复制