1

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

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

...在进行 OLE 调用之前,必须将当前线程设置为单线程单元 (STA) 模式。确保您的 Main 函数上标记了 STAThreadAttribute ...

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

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

有没有人遇到过同样的情况?我能做些什么来解决这个问题吗?

4

3 回答 3

2

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

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

于 2009-06-30T12:07:55.303 回答
1

我最近在尝试从网络摄像头读取图像时遇到了这个问题。我最终做的是创建一个产生新 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();
    }
}
于 2011-02-16T20:44:09.083 回答
0

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

于 2009-09-08T09:50:33.133 回答