我有一个主GUI,我从一个单独的线程中开始一个长时间运行的方法。 现在,在这个单独的线程中,我需要创建并显示一个新表单。 但是,当我显示这个新表单时,所有控件都被卡住了,窗口显示“没有响应”。
哪种解决方法最好?
问候
托马斯
答案 0 :(得分:4)
将创建新GUI的代码放入主GUI类中,然后调用主GUI的Invoke方法,或者引发主GUI可以订阅的事件,以了解何时触发新的GUI。如果选择后者,请务必使用InvokeRequired确定是否可以直接调用创建新GUI的方法,或者是否需要使用Invoke返回GUI线程来创建新GUI。
答案 1 :(得分:2)
您需要了解Control.BeginInvoke / Invoke以及所有这些意义。请记住,所有UI操作都需要在主线程(UI线程)上进行,因为这是拥有消息泵的线程。您需要回调该线程才能执行UI操作。
以下是BeginInvoke / Invoke内容的介绍:http://weblogs.asp.net/justin_rogers/pages/126345.aspx
为了进一步提供帮助,这里有一个完整的工作代码示例,应该突出基础知识。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var worker = new Worker(this);
worker.Start();
}
public void updateLabel(int value)
{
if(label1.InvokeRequired) { // check if on UI thread
//If true use begin invoke to call update on UI thread
//this calls the anonymous delegate in the UI thread
//that then calls the updateLabel function again to set the label's text
label1.BeginInvoke(new MethodInvoker(() => this.updateLabel(value)));
return;
}
label1.Text = value.ToString();
}
public void showNewForm()
{
if(this.InvokeRequired) { // check if on UI thread
this.BeginInvoke(new MethodInvoker(this.showNewForm)); // we need to create the new form on the UI thread
return;
}
var anotherForm = new Form1();
anotherForm.Show();
}
}
class Worker
{
private volatile bool stop = false;
private Form1 form;
public Worker(Form1 form)
{
this.form = form;
}
public bool Stop
{
get
{
return stop;
}
set
{
stop = value;
}
}
public void Start()
{
var thread = new Thread(this.work);
thread.IsBackground = true;
thread.Start();
}
private void work()
{
int i = 0;
while(!stop) {
i++;
Thread.Sleep(100);
form.updateLabel(i);
if(i == 50) {
form.showNewForm(); // call into form
// can also do the invokerequired check here and create new form w/ anonymous functions
// however, I'd recommend keeping all the UI code in the same place.
}
}
}
}
答案 2 :(得分:0)
使用Form.Show代替Form.ShowDialog。您还可以使用BackgroundWorker执行并发任务。