Suspend thread until WebBrowser has finished loading
<p>I'm trying to navigate across a website and do some work on the pages programmatically using a WebBrowser control in a Windows Form. I found <a href="http://stackoverflow.com/questions/8258062/whats-the-best-way-to-pause-loop-while-webbrowser-is-loading-page">this</a> while looking for a way to block my thread until the WebBrowser's DocumentCompleted event is triggered. Given that, here's my current code:</p>

<pre><code>public partial class Form1 : Form
{
    private AutoResetEvent autoResetEvent;

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Thread workerThread = new Thread(new ThreadStart(this.DoWork));
        workerThread.SetApartmentState(ApartmentState.STA);
        workerThread.Start();
    }

    private void DoWork()
    {
        WebBrowser browser = new WebBrowser();
        browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(browser_DocumentCompleted);
        browser.Navigate(login_page);
        autoResetEvent.WaitOne();
        // log in

        browser.Navigate(page_to_process);
        autoResetEvent.WaitOne();
        // process the page
    }

    private void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        autoResetEvent.Set();
    }
}
</code></pre>

<p>The thread doesn't look necessary, but it will be when I expand this code to accept requests over the network (the thread will listen for connections, then process the requests). Also, I can't just put the processing code inside the DocumentCompleted handler, since I have to navigate to several different pages and do different things on each one.</p>

<p>Now, from what I understand, the reason this doesn't work is because the DocumentCompleted event uses the same thread that WaitOne() is being called in, so the event will not be fired until WaitOne() returns (never, in this case).</p>

<p>What's interesting is that if I add a WebBrowser control to the form from the toolbox (drag-and-drop), then navigate using that, this code works perfectly (with no changes other than putting the call to Navigate inside a call to Invoke - see below). But if I manually add a WebBrowser control to the Designer file, it doesn't work. And I don't really want a visible WebBrowser on my form, I just want to report the results.</p>

<pre><code>public delegate void NavigateDelegate(string address);
browser.Invoke(new NavigateDelegate(this.browser.Navigate), new string[] { login_page });
</code></pre>

<p>My question, then, is: What's the best way to suspend the thread until the browser's DocumentCompleted event fires?</p>
