2

When I do the following (Actually I repeat the same whole code with different web pages):

        Navigator nav;
        nav = new Navigator();
        nav.Browser.Navigate("http://www.amazon.com/gp/search/ref=sr_adv_b/?search-alias=stripbooks&unfiltered=1&field-keywords=&field-author=&field-title=&field-isbn=0471848573+&field-publisher=&node=&field-p_n_condition-type=&field-feature_browse-bin=&field-binding_browse-bin=&field-subject=&field-language=&field-dateop=&field-datemod=&field-dateyear=&sort=relevanceexprank&Adv-Srch-Books-Submit.x=18&Adv-Srch-Books-Submit.y=4");
        while (nav.Browser.ReadyState != WebBrowserReadyState.Complete) Application.DoEvents();
        nav.Dispose();

Navigator is a Form that contains a public WebBrowser and that's it. You can test it yourself and I think the same will happen, but it doesn't happen every single time. You might need to put it in a loop and repeat it a few times for the problem to happen.

Juan
  • 15,274
  • 23
  • 105
  • 187
  • This is the url of the web page that opens on IE: http://www.amazon.com/s/ref=sr_err_sr_1?ie=UTF8&search-alias=aps&field-keywords=searchzus%26cb2361%26ajaxReload%3D1%20 wonder if that ajaxReload have something to do with the problem – Juan Sep 08 '10 at 19:29
  • 1
    No repro. Try http://msn.com for more objectionable side effects. – Hans Passant Sep 08 '10 at 19:32
  • @Hans Passant: I edited the question and changed the Url, the previous one wasn't causing the problem, but this one is. – Juan Sep 08 '10 at 19:36
  • Well, you owe me 5 minutes of my life. – Hans Passant Sep 08 '10 at 19:41
  • 1
    No repro with the URL in the comment nor with msn.com. I created a WinForms project, added a button to the main form. Created a new form named Navigator with a public WebBrowser inside. And pasted your code in the button click event handler of the main form. – Timores Sep 08 '10 at 19:45
  • Are you guys using Windows 7? – Juan Sep 08 '10 at 19:50

3 Answers3

2

Make your Navigator form look like this:

public partial class Navigator : Form {
    private bool done;

    public Navigator() {
        InitializeComponent();
        Browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(Browser_DocumentCompleted);
    }
    void Browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
        if (e.Url == Browser.Url) done = true;
    }
    public bool Completed {
        get { return done; }
    }
}

And your loop like this:

        Navigator nav;
        nav = new Navigator();
        nav.Browser.Navigate("http://www.amazon.com/gp/search/ref=sr_adv_b/?search-alias=stripbooks&unfiltered=1&field-keywords=&field-author=&field-title=&field-isbn=0471848573+&field-publisher=&node=&field-p_n_condition-type=&field-feature_browse-bin=&field-binding_browse-bin=&field-subject=&field-language=&field-dateop=&field-datemod=&field-dateyear=&sort=relevanceexprank&Adv-Srch-Books-Submit.x=18&Adv-Srch-Books-Submit.y=4"); //        http://msn.com"); //stackoverflow.com/questions/3661536/while-true-application-doevents-doesnt-know-when-the-program-finishes");
        this.Enabled = false;
        while (!nav.Completed) Application.DoEvents();
        this.Enabled = true;
        nav.Dispose();
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Hans, shouldn't he use a `using` block around `nav`? – John Saunders Sep 08 '10 at 19:49
  • You are pulling the rug out from under IE *before* it is done. Note the test in the DocumentCompleted event. – Hans Passant Sep 08 '10 at 19:49
  • I removed the `this.Enabled = false` and still worked. Is it really necessary? – Juan Sep 08 '10 at 19:51
  • Yes, this is *very* necessary. Calling DoEvents() while the user interface is still enabled is very dangerous. The user could close the form or click the button again while your code is looping. That never comes to a good end. – Hans Passant Sep 08 '10 at 20:06
  • 1
    I'm pretty stunned that none of my answers has been helpful so-far. What's the problem with them? – Hans Passant Sep 08 '10 at 20:07
  • Wait. That didn't solved it. That while should have beenn `while(!nav.Completed) Application.DoEvents();` instead of `while(nav.Completed) Application.DoEvents();`. If I put it this way the problem persists. – Juan Sep 08 '10 at 20:12
  • Crud, typo. Works on my machine. – Hans Passant Sep 08 '10 at 20:23
  • Sorry, my bad. I changed `if(e.Url == Browser.Url)` to `if (e.Url == Browser.Url && Browser.ReadyState == WebBrowserReadyState.Complete)`. Whenever I remove the ReadyState check the problem stops. Should I just not check the ReadyState then? – Juan Sep 08 '10 at 20:25
  • 1
    There is no ReadyState check in my code. The DocumentCompleted event is important. – Hans Passant Sep 08 '10 at 20:27
  • I added it. Just to be 100% sure the page has loaded. – Juan Sep 08 '10 at 20:29
  • And yes, checking `ReadyState` IS the cause of the problem. Just removed it from my real application and everything works fine now. Isn't it weird? – Juan Sep 08 '10 at 20:30
  • Hans, it took a few Posts but you finally got his program working. Cheers. – H H Sep 08 '10 at 20:42
  • ReadyState doesn't actually tell you that the browser is ready, it only tells you that the frame is complete. There are multiple frames, this Amazon link behaves particularly crazy in the regular browser. If you keep your original code and just remove the ReadyState check then you'll abort the browser before it really got anywhere. – Hans Passant Sep 08 '10 at 20:44
  • &%#$+, I already showed you how to do this 4 days ago: http://stackoverflow.com/questions/3641296/create-thread-just-like-if-it-were-a-separated-application-in-c/3642766#3642766 – Hans Passant Sep 08 '10 at 20:59
2

I had the same problem when I tried to invoke Dispose() function of a WebBrowser in a ThreadPool Queued executing.

I started a Timer in the delegated of Control.Invoke to resolve it. This is my code:

    public delegate void SucceedDelegate();
    // calling by ThreadPool.QueueUserWorkItem(succeed);
    protected void succeed(Object obj){
        Application.OpenForms[0].Invoke(new SucceedDelegate(succeed0));
    }
    private void succeed0()
    {
        Timer timer = new Timer();
        timer.Interval = 1;
        timer.Tick += succeedHandler;
        timer.Start();
    }
    private void succeedHandler(object sender, EventArgs e)
    {
        ((Timer)sender).Stop();
        succeed00();
    }
    private void succeed00()
    {
        //call WebBrowser.Dispose() here
    }

It's ugly, but working well.

gneheix
  • 21
  • 2
1

Try to add another DoEvents AFTER the loop, just before the nav.Dispose()

            Navigator nav;
            nav = new Navigator();
            nav.Browser.Navigate("http://www.amazon.com/gp/search/ref=sr_adv_b/?search-alias=stripbooks&unfiltered=1&field-keywords=&field-author=&field-title=&field-isbn=0471848573+&field-publisher=&node=&field-p_n_condition-type=&field-feature_browse-bin=&field-binding_browse-bin=&field-subject=&field-language=&field-dateop=&field-datemod=&field-dateyear=&sort=relevanceexprank&Adv-Srch-Books-Submit.x=18&Adv-Srch-Books-Submit.y=4");
            while (nav.Browser.ReadyState != WebBrowserReadyState.Complete) Application.DoEvents();
            Application.DoEvents(); // will avoid launching of IE
            nav.Dispose();
Micha Kaufman
  • 777
  • 7
  • 11