1

首先,我需要的是 - n WebBrowser-s,每个都在自己的窗口中做自己的工作。用户应该能够看到它们全部,或者只看到它们中的一个(或一个都没有),并在每个上执行命令。有一个主窗体,没有浏览器,这个包含我的应用程序的控制面板。

关键特征是,每个浏览器都登录到安全网页,并且需要尽可能长时间地保持登录状态。好吧,我已经做到了,但我担心我的方法有问题。

问题是:

下面的代码是否有效,或者更确切地说是可能导致问题的讨厌的黑客攻击:

internal class SessionList : List<Session> {

    public SessionList(Server main) {
        MyRecords.ForEach(record => {
            var st = new System.Threading.Thread((data) => {
                var s = new Session(main, data as MyRecord);
                this.Add(s);
                Application.Run(s);
                Application.ExitThread();
            });
            st.SetApartmentState(System.Threading.ApartmentState.STA);
            st.Start(record);
        });
    }

    // some other uninteresting methods here...

}

这里发生了什么?Session继承自Form,所以它创建一个表单,将WebBrowser放入其中,并具有对网站进行操作的方法。WebBrowser 需要在 STA 线程中运行,因此我们为每个浏览器提供一个。其中最有趣的部分是Application.Run(s). 它使新创建的表单具有活力和交互性。Application.ExitThread()在浏览器窗口关闭并释放其控件后调用下一个。主应用程序保持活动状态以执行其余的清理工作。

当用户选择“退出”或“关闭”选项时 - 首先浏览器线程结束,因此Application.ExitThread()被调用。一切正常,但我在任何地方都能读到“主 GUI 线程”——在这里——我创建了许多 GUI 线程。我使用线程安全方法处理主表单和新表单(会话)之间的通信Invoke()。这一切都有效,那么它是对还是错?

Application.Run()在一个应用程序中多次使用是否一切正常?:) 丑陋的 hack 还是正常的做法?如果我从会话表单线程启动 WebBrowser,此代码将终止。它打败了我为什么。但是,如果我Url从任何其他线程启动 WebBrowser(通过更改其属性),它就可以工作。我想更多地了解此类应用程序中真正发生的事情。但最重要的是 - 我想知道我的“应用程序中的应用程序”的想法是否可行。

我不确定到底是Application.Run()做什么的。没有它,在新线程中创建的表单将毫无反应。我怎么可能打电话Application.Run()多次?它似乎完全按照它应该做的,但对我来说似乎是一个没有记录的功能。我几乎可以肯定,崩溃是由 WebBrowser 组件本身引起的(因为它不是完全“托管”和“原生”的)。但也许是别的东西。

4

1 回答 1

4

在一个应用程序中多次使用 Application.Run() 是否一切正常?:) 丑陋的 hack 还是正常的做法?

两者中的一些;)这是完全可以接受的,因为它将按您的预期运行,但这并不完全是“正常做法”。

我不确定 Application.Run() 到底是做什么的。

Application.Run基本上做了几件事。首先,它将属性安装SynchronizationContext到线程中,以便 Windows 窗体正常运行。然后它在该线程中启动 Windows 消息处理,该线程处理来自 Windows 进入线程的所有消息。这就是允许表单正常工作的原因。

这样做并没有什么特别的错误,但这不是标准做法。鉴于您的设计目标,我确实质疑仅通过启动单独的进程而不是尝试在单独的线程中运行每个操作是否会更好地服务。

于 2012-06-11T16:36:34.100 回答