Search code examples
c#eventswebbrowser-controlautoresetevent

Wait for WebBrowser DocumentCompleted using AutoResetEvent


I want my function to wait until the event WebBrowser.DocumentCompleted is completed.

I am using AutoResetEvent and here is my code:

private static WebBrowser _browser = new WebBrowser();
private static AutoResetEvent _ar = new AutoResetEvent(false);

private bool _returnValue = false;

public Actions() //constructor
{
        _browser.DocumentCompleted += PageLoaded;
}

public bool MyFunction()
{
    _browser.Navigate("https://www.somesite.org/");
    _ar.WaitOne(); // wait until receiving the signal, _ar.Set()
    return _returnValue;
}

private void PageLoaded(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    // do not enter more than once for each page
    if (e.Url.AbsolutePath != (sender as WebBrowser).Url.AbsolutePath)
        return;

    _returnValue = true;

    _ar.Set(); // send signal, unblock my function
}

Here my problem is, PageLoaded never gets fired, and my function gets stuck on _ar.WaitOne();. How can I fix this issue ? perhaps there is another way to achieve this ?


Solution

  • Here is how you can synchronously get the page data of a website. This will help me build my web automation API. Special thanks to @Noseratio he helped me finding this perfect answer.

    private static string _pageData = "";
    
    public static void MyFunction(string url)
    {
        var th = new Thread(() =>
        {
            var br = new WebBrowser();
            br.DocumentCompleted += PageLoaded;
            br.Navigate(url);
            Application.Run();
        });
        th.SetApartmentState(ApartmentState.STA);
        th.Start();
        while (th.IsAlive)
        {
        }
    
        MessageBox.Show(_pageData);
    }
    
    static void PageLoaded(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        var br = sender as WebBrowser;
        if (br.Url == e.Url)
        {
             _pageData = br.DocumentText;
            Application.ExitThread();   // Stops the thread
         }
        }
    }