views:

351

answers:

1

hey i am trying to create two webbrowsers on a sperate thread from the rest of the form. one goes to tabpage1 and the other is added to tabpage2. the first browser creates fine to page1 however the second browser wont add and the error "Unable to get the window handle for the 'WebBrowser' control. Windowless ActiveX controls are not supported." happens. heres my code:

private Thread t;  
WebBrowser webBrowser1, webBrowser2;  
public delegate void Addc1(Control o);  
public delegate void Addc2(Control o);  
public Addc1 AddControl1;  
public Addc2 AddControl2;  
public Form1()  
{  
        InitializeComponent();  
        AddControl1 = new Addc1(AddTabControl1);  
        AddControl2 = new Addc2(AddTabControl2);         
}        
private void button2_Click(object sender, EventArgs e)  
{  
        t = new Thread(new ThreadStart(this.UIStart));  
        t.SetApartmentState(ApartmentState.STA);  
        t.Start();  
}  
public void UIStart()  
{  
            WebBrowser webBrowser1 = new WebBrowser();  
            webBrowser1.Location = new System.Drawing.Point(1,1);  
            webBrowser1.Size = new System.Drawing.Size(936, 35);  
            webBrowser1.DocumentCompleted += new System.Windows.Forms.WebBrowserDocumentCompletedEventHandler(this.webBrowser2_DocumentCompleted);  
            tabPage1.Invoke(AddControl1, new Object[] { webBrowser1 });  

            WebBrowser webBrowser2 = new WebBrowser();  
            webBrowser2.Location = new System.Drawing.Point(1,1);  
            webBrowser2.Size = new System.Drawing.Size(936, 935);  
            webBrowser2.DocumentCompleted += new System.Windows.Forms.WebBrowserDocumentCompletedEventHandler(this.webBrowser2_DocumentCompleted);    
            tabPage2.Invoke(AddControl2, new Object[] { wedBrowser2 });  


            webBrowser1.Navigate("www.ask.com");  
            webBrowser2.Navigate("www.google.com");  
        }  
        public void AddTabControl1(Control o)  
        {  
            tabPage1.Controls.Add(o);  
        }  
        public void AddTabControl2(Control o)  
        {  
            tabPage2.Controls.Add(o);  
        }  
}  

as i said the webbrowser1 will create and navigate but the other one will add to the controls on page2 but will not create. any ideas? thanks adds

+2  A: 

You are violating several threading rules:

  • WebBrowser is an ActiveX control with single-threaded apartment requirements. You are correctly setting the thread to STA but you are violating the second requirement: an STA thread must pump a message loop. You didn't get that far yet, but the DocumentCompleted event will never fire.
  • Windows requires child controls to belong to the same thread as their parent. In your case, there's a nasty mismatch. The AxHost wrapper will be created on the UI thread due to the Controls.Add() call but the native window handle that the WebBrowser uses may not. I think that's the source of the exception you get.

You can't make this work as you intended, a web browser is simply not a chunk of code that can handle multiple threads. Even if you do create it on the correct thread, calls made on a background thread will be marshaled by COM to implement the STA contract, there is no concurrency.

Using it on a separate STA thread that pumps a message loop (Application.Run) is fine but the form and its controls must be created on that same thread.

Hans Passant