代码之家  ›  专栏  ›  技术社区  ›  xsl Fredrik Hedblad

STA、MTA和OLE噩梦

  •  1
  • xsl Fredrik Hedblad  · 技术社区  · 15 年前

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

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

    …当前线程必须设置为 单线程公寓(STA)模式 在进行OLE调用之前。确保 你的主要功能 在上面标记了StathreadAttribute…

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

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

    有人处于同样的情况吗?我能做些什么来解决这个问题吗?

    3 回复  |  直到 13 年前
        1
  •  2
  •   devdimi    15 年前

    您可以尝试生成新线程,并在其上使用0调用coInitialize(aparment线程),然后在此线程中运行应用程序。 但是,您不能直接在这个线程中更新控件,您应该对每个UI修改使用control.invoke。

    我不知道这是否会奏效,但你可以试试。

        2
  •  1
  •   Gustavo Mori    13 年前

    我最近在尝试从网络摄像机读取图像时遇到了这个问题。我最终做的是创建一个生成新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
  •  0
  •   xsl Fredrik Hedblad    15 年前

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

    推荐文章