【问题标题】:Single-threaded apartment - cannot instantiate ActiveX control单线程单元 - 无法实例化 ActiveX 控件
【发布时间】:2010-11-27 22:56:24
【问题描述】:

我需要获取有关 HTML 页面中应用的 CSS 样式的信息。我使用 AxWebBrowser 并迭代 IHTMLDOMNode。我能够获取我需要的所有数据并将代码移动到我的应用程序中。问题是这部分在后台工作人员内部运行,并且在尝试实例化控件时出现异常。

AxWebBrowser browser = new AxWebBrowser();

ActiveX control '8856f961-340a-11d0-a96b-00c04fd705a2' cannot be instantiated
because the current thread is not in a single-threaded apartment.

除了 AxWebBrowser 之外,还有什么方法可以解决这个问题或其他选项吗?

【问题讨论】:

    标签: .net exception sta single-threaded


    【解决方案1】:

    您遇到的问题是大多数后台线程/工作者 API 将在多线程单元状态下创建线程。错误消息表明该控件要求线程是单线程单元。

    您可以通过自己创建一个线程并在该线程上指定 STA 单元状态来解决此问题。

    var t = new Thread(MyThreadStartMethod);
    t.SetApartmentState(ApartmentState.STA);
    t.Start();
    

    【讨论】:

    • 谢谢,这很好用。还有一个问题/问题。我使用的类只是类,AxWebBrowser 看起来需要添加到 this.Controls() 中。有没有办法伪造控件?或者我需要为此分开表格吗?
    • @martin.malek 没有很好的方法来伪造它。最好的办法是创建一个新表单。
    • 你好,代码应该是t.SetApartmentState(ApartmentState.STA);
    • 确认道金斯的评论,我也不得不把它改成 AppartmentState.STA。
    • 请注意,此代码不足以正确实现 STA 线程,它还必须泵送消息循环。特别是 WebBrowser 会发生故障,它不会触发 DocumentCompleted 事件。检查this post 以获取替代方案。
    【解决方案2】:

    继续在应用程序的主条目中添加 [STAThread],这表明 COM 线程模型是单线程单元 (STA)

    示例:

    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new WebBrowser());
        }
    }
    

    【讨论】:

    • 在框架 4.5 中不起作用 - 在最后一行给出无效参数
    【解决方案3】:

    如果您在应用程序的主条目中使用了[STAThread],但仍然出现错误,您可能需要对控件进行线程安全调用...如下所示。在我遇到同样问题的情况下,以下解决方案有效!

    Private void YourFunc(..)
    {
        if (this.InvokeRequired)
        {
            Invoke(new MethodInvoker(delegate()
            {
               // Call your method YourFunc(..);
            }));
        }
        else
        {
            ///
        }
    

    【讨论】:

    • 这里应该调用什么?浏览器?在哪个州?就我而言,浏览器位于对话框上。
    【解决方案4】:

    我的问题是我的 Main 方法标记为 async。因此,只需将其设为 static void 并将 .wait() 添加到所有 awaitable 方法中即可修复它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-06
      • 2012-05-18
      • 2011-01-13
      • 1970-01-01
      • 1970-01-01
      • 2013-06-02
      • 1970-01-01
      相关资源
      最近更新 更多