让mainThread再次运行?

时间:2011-09-21 14:30:16

标签: winforms multithreading browser

您好,

我有一个托管WCF服务(NamedPipes)的winform应用程序。在接听电话时,将触发一个事件,然后创建并打开一个表格。问题是我得到了跟随异常

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

在winforms InitializeComponent方法中创建System.Windows.Forms.WebBrowser时?

我认为另一个线程正在运行even(工作线程),如何让主线程运行该事件?

我当时没有打开任何winform,因此我无法使用InvokeRequired。

BestRegards

Edit1:请不要我正在使用

[STAThread]
public static void Main(string[] args)
{
Application.Run(_instance);
}

3 个答案:

答案 0 :(得分:1)

这些调用是在线程池线程上进行的。它们不适合显示任何UI。您需要创建自己正确风格的线程:

        var t = new Thread(() => {
            Application.Run(new Form1());
        });
        t.SetApartmentState(ApartmentState.STA);
        t.Start();

还有其他一些实际问题,你不能在没有用户参与的情况下弹出一个窗口。典型的不幸是用户偶然关闭它而没有看到它或窗口消失在用户正在使用的窗口后面。如果您已有用户界面,请务必使用Control.BeginInvoke()让主线程显示窗口。考虑使用NotifyIcon进行柔和触摸,在托盘通知区域中显示气球以提醒用户。

答案 1 :(得分:0)

该WCF调用很可能是在主UI线程以外的线程上进行的。必须从UI线程创建和访问所有UI控件(包括ActiveX控件),并且只能访问UI线程。您得到的错误表明创建线程甚至不在单线程单元(STA)中,这也是一个要求。

要在主UI线程上执行代码,请使用Control.Invoke方法。它会将委托的执行封送到托管目标ControlForm的线程上。

如果您没有立即可用的ControlForm,则需要创建一个。您可能还必须创建一个运行消息循环的线程。这可以使用Application.Run完成。创建一个可用于调用Form的隐藏Invoke非常简单。

这可能是它的样子。

void SomeMethodExecutingOnThreadPool()
{
  var form = null;
  var mre = new ManualResetEvent(false);

  // Create the UI thread.
  new Thread(
    () =>
    {
      form = new Form();
      form.Load += 
        (sender, args) => 
        {
          mre.Set();
        }
      Application.Run(form);
    }).Start();

  // Wait for the UI thread to initialize.
  mre.WaitOne(); 

  // You can now call Invoke.
  form.Invoke(/* ... */);
}

答案 2 :(得分:0)

我的解决方案是在启动时创建一个虚拟winform,当我需要主UI线程时,我将在这个虚拟形式上使用invoke。

它将使用更多的资源,但我没有看到更简单的方法。