运行多个UI线程

9

问题请跳到底部;这只是一些额外信息

我正在使用一个组件(GeckoFX)来渲染一些网站,虽然很好,但它只能在Windows Form中使用;因为它必须绑定到可以被绘制的WinForms对象。由于所有的WinForms都在同一个线程中运行,我一次只能使用一个GeckoFX实例;所以我决定创建一个“工作类”,以WinForm的形式存在,并在其中添加所有逻辑。该表单不需要与主表单通信。

现在我可以启动10个窗口,它们最终会工作,但每个新窗口都会等待所有其他窗口处理完其所有的GeckoFX事件,因为您不能在一个线程上使用多个实例。此外,浏览器必须在UIThread上。

是否可能创建多个UI线程(每个窗体一个)?

我见过有人这样做([编辑:删除了“坏”链接]),但没有人能够使他的代码示例工作。最初使其工作的人使用了某种自定义消息泵来完成这种事情,但我不知道如何实现这样的功能。

4个回答

9

我认为你所询问的并不是你真正想要的,但是对于每个线程创建一个消息泵很容易,你只需要在每个线程中调用一次 Application.Run。

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Thread t1 = new Thread(Main_);
        Thread t2 = new Thread(Main_);

        t1.Start();
        t2.Start();

        t1.Join();
        t2.Join();
    }

    static void Main_()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

这差不多是我想要的,但是GeckoFX现在抱怨内存访问违规,所以我现在只能继续运行我的单线程 :-) - Jan Jongboom
1
请注意,您不必创建一个表单来运行消息循环 - 只需在线程上使用无参数的Application.Run()即可。 - ulatekh

3

使用Application.DoEvents()方法。
或者
创建多线程窗体:

    Thread form2Thread;
    Form2 form2;

    private void Form1_Load(object sender, EventArgs e)
    {
        form2Thread = new Thread(RunForm2);
        form2Thread.SetApartmentState(ApartmentState.STA);
        form2Thread.Name = "Form2 Thread";   // looks nice in Output window
        form2Thread.Start();
    }

    public void RunForm2()
    {
        form2 = new Form2();
        Application.Run(form2);
    }

这不是非模态的意思。http://www.programmersheaven.com/2/FAQ-WinForm-Modal-Non-Modal - Wim Coenen
已经有一些东西了,但是从一个UIThread创建新的UI线程会产生奇怪的行为,所以没有起作用。 - Jan Jongboom

3
GeckoFx 不需要表单。
GeckoWebBrowser wb = new GeckoWebBrowser();
wb.CreateControl(); //<-- the magic lays here!
wb.DocumentCompleted += delegate{ MessageBox.Show(wb.DocumentTitle); };
wb.Navigate("http://mysite.com");

1

看起来是可能的。

我使用背景知识,打开了TestApp,并在线程/消息泵#2上创建了一个新的Form1:

private void button2_Click(object sender, EventArgs e) {
    helper.Background(() => {
        Form1 form2 = new Form1();
        form2.Show();
    });
}

第二个窗口响应鼠标点击等操作。

实际上还没有验证是否一切正常,我使用的免费版Visual Studio Express Edition缺少“线程”调试窗口,咳咳。所以我有点不清楚。不过它似乎是有效的。请告诉我 :-)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接