如何从非gui线程C#中创建表单

时间:2009-06-11 19:11:03

标签: c#

我有一个主GUI,我从一个单独的线程中开始一个长时间运行的方法。 现在,在这个单独的线程中,我需要创建并显示一个新表单。 但是,当我显示这个新表单时,所有控件都被卡住了,窗口显示“没有响应”。

哪种解决方法最好?

问候

托马斯

3 个答案:

答案 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执行并发任务。