【问题标题】:STA, MTA and OLE nightmareSTA、MTA 和 OLE 的噩梦
【发布时间】:2009-06-30 11:31:19
【问题描述】:

我必须将 .NET 应用程序作为插件包含到另一个 .NET 应用程序中。插件接口要求我从模板表单继承。然后在加载插件时将表单附加到 MDI 中。

到目前为止一切正常,但每当我注册拖放事件、为组合框设置自动完成模式或在各种其他情况下,我都会收到以下异常:

...当前线程必须设置为 单线程单元(STA)模式 在可以进行 OLE 调用之前。确保 你的主要功能有 STAThreadAttribute 标上就可以了...

主应用程序在 MTA 中运行并由另一家公司开发,因此我无能为力。

我尝试在 STA 线程中执行导致这些异常的事情,但这也没有解决问题。

有人遇到过同样的情况吗?有什么办法可以解决这个问题吗?

【问题讨论】:

    标签: .net multithreading sta mta


    【解决方案1】:

    您可以尝试生成新线程并在其上调用带有 0 的 CoInitialize(aparment 线程)并在此线程中运行您的应用程序。 但是,您不会直接在此线程中更新控件,您应该使用 Control.Invoke 进行每次 UI 修改。

    我不确定这是否会奏效,但你可以试试。

    【讨论】:

    • 感谢您的建议。我试过了,但是当我调用一个由 MTA 线程创建的 UI 元素时,我得到了同样的错误。
    • 可以控制应用程序的启动方式吗?比你可以将它包装在容器应用程序中。创建线程,初始化 COM,然后调用程序的 Main 方法。根据应用程序,这可能会起作用或不起作用并导致主程序崩溃,但可能是您最后的手段。 (在反编译和更改主应用程序之前,这可能是非法的。)您也可以尝试联系开发它的公司。
    • 启动一个新线程 t,使用 t.SetApartmentState(System.Threading.ApartmentState.STA), t.Start() - 不会出错。它可以正常工作,并在我的大型应用程序中进行了测试。
    【解决方案2】:

    我最近在尝试从网络摄像头读取图像时遇到了这个问题。我最终做的是创建一个方法来生成一个新的 STA 线程,在该线程上运行单线程方法。

    问题

    private void TimerTick(object sender, EventArgs e)
    {
       // pause timer
       this.timer.Stop();
    
            try
            {
                // get next frame
                UnsafeNativeMethods.SendMessage(this.captureHandle, WindowsMessageCameraGetFrame, 0, 0);
    
                // copy frame to clipboard
                UnsafeNativeMethods.SendMessage(this.captureHandle, WindowsMessageCameraCopy, 0, 0);
    
                // notify event subscribers
                if (this.ImageChanged != null)
                {
                    IDataObject imageData = Clipboard.GetDataObject();
    
                    Image image = (Bitmap)imageData.GetData(System.Windows.Forms.DataFormats.Bitmap);
    
                    this.ImageChanged(this, new WebCamEventArgs(image.GetThumbnailImage(this.width, this.height, null, System.IntPtr.Zero)));
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error capturing the video\r\n\n" + ex.Message);
                this.Stop();
            }
        }
       // restart timer
       Application.DoEvents();
    
       if (!this.isStopped)
       {
          this.timer.Start();
       }
    }
    

    解决方法:将单线程逻辑移到自己的方法中,从新的STA线程调用该方法。

    private void TimerTick(object sender, EventArgs e)
    {
        // pause timer
        this.timer.Stop();
    
        // start a new thread because GetVideoCapture needs to be run in single thread mode
        Thread newThread = new Thread(new ThreadStart(this.GetVideoCapture));
        newThread.SetApartmentState(ApartmentState.STA);
        newThread.Start();
    
        // restart timer
        Application.DoEvents();
    
        if (!this.isStopped)
        {
            this.timer.Start();
        }
    }
    
    /// <summary>
    /// Captures the next frame from the video feed.
    /// This method needs to be run in single thread mode, because the use of the Clipboard (OLE) requires the STAThread attribute.
    /// </summary>
    private void GetVideoCapture()
    {
        try
        {
            // get next frame
            UnsafeNativeMethods.SendMessage(this.captureHandle, WindowsMessageCameraGetFrame, 0, 0);
    
            // copy frame to clipboard
            UnsafeNativeMethods.SendMessage(this.captureHandle, WindowsMessageCameraCopy, 0, 0);
    
            // notify subscribers
            if (this.ImageChanged!= null)
            {
                IDataObject imageData = Clipboard.GetDataObject();
    
                Image image = (Bitmap)imageData.GetData(System.Windows.Forms.DataFormats.Bitmap);
    
                // raise the event
                this.ImageChanged(this, new WebCamEventArgs(image.GetThumbnailImage(this.width, this.height, null, System.IntPtr.Zero)));
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error capturing video.\r\n\n" + ex.Message);
            this.Stop();
        }
    }
    

    【讨论】:

      【解决方案3】:

      更新:公司发布了新的STA版本。该问题不再相关。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-21
        • 2020-03-14
        • 2010-11-13
        • 2010-12-22
        • 1970-01-01
        相关资源
        最近更新 更多