C# how to wait for a webpage to finish loading before continuing

后端 未结 11 1218
暖寄归人
暖寄归人 2020-11-27 03:33

I\'m trying to create a program to clone multiple bugs at a time through the web interface of our defect tracking system. How can I wait before a page is completely loaded

相关标签:
11条回答
  • 2020-11-27 03:36

    Best way to do this without blocking the UI thread is to use Async and Await introduced in .net 4.5.
    You can paste this in your code just change the Browser to your webbrowser name. This way, your thread awaits the page to load, if it doesnt on time, it stops waiting and your code continues to run:

    private async Task PageLoad(int TimeOut)
        {
            TaskCompletionSource<bool> PageLoaded = null;
            PageLoaded = new TaskCompletionSource<bool>();
            int TimeElapsed = 0;
            Browser.DocumentCompleted += (s, e) =>
            {
                if (Browser.ReadyState != WebBrowserReadyState.Complete) return;
                if (PageLoaded.Task.IsCompleted) return; PageLoaded.SetResult(true);
            };
            //
            while (PageLoaded.Task.Status != TaskStatus.RanToCompletion)
            {
                await Task.Delay(10);//interval of 10 ms worked good for me
                TimeElapsed++;
                if (TimeElapsed >= TimeOut * 100) PageLoaded.TrySetResult(true);
            }
        }
    

    And you can use it like this, with in an async method, or in a button click event, just make it async:

    private async void Button1_Click(object sender, EventArgs e)
    {
       Browser.Navigate("www.example.com");
       await PageLoad(10);//await for page to load, timeout 10 seconds.
       //your code will run after the page loaded or timeout.
    }
    
    0 讨论(0)
  • 2020-11-27 03:36

    yuna and bnl code failed in the case below;

    failing example:

    1st one waits for completed.but, 2nd one with the invokemember("submit") didnt . invoke works. but ReadyState.Complete acts like its Completed before its REALLY completed:

    wb.Navigate(url);
    while(wb.ReadyState != WebBrowserReadyState.Complete)
    {
       Application.DoEvents();
    }
    MessageBox.Show("ok this waits Complete");
    
    //navigates to new page
    wb.Document.GetElementById("formId").InvokeMember("submit");
    while(wb.ReadyState != WebBrowserReadyState.Complete)
    {
       Application.DoEvents();
    }
    MessageBox.Show("webBrowser havent navigated  yet. it gave me previous page's html.");  
    var html = wb.Document.GetElementsByTagName("HTML")[0].OuterHtml;
    

    how to fix this unwanted situation:

    usage

        public myForm1 {
    
            myForm1_load() { }
    
            // func to make browser wait is inside the Extended class More tidy.
            WebBrowserEX wbEX = new WebBrowserEX();
    
            button1_click(){
                wbEX.Navigate("site1.com");
                wbEX.waitWebBrowserToComplete(wb);
    
                wbEX.Document.GetElementById("input1").SetAttribute("Value", "hello");
                //submit does navigation
                wbEX.Document.GetElementById("formid").InvokeMember("submit");
                wbEX.waitWebBrowserToComplete(wb);
                // this actually waits for document Compelete. worked for me.
    
                var processedHtml = wbEX.Document.GetElementsByTagName("HTML")[0].OuterHtml;
                var rawHtml = wbEX.DocumentText;
             }
         }
    
    //put this  extended class in your code.
    //(ie right below form class, or seperate cs file doesnt matter)
    public class WebBrowserEX : WebBrowser
    {
       //ctor
       WebBrowserEX()
       {
         //wired aumatically here. we dont need to worry our sweet brain.
         this.DocumentCompleted += (o, e) => { webbrowserDocumentCompleted = true;};
       }
         //instead of checking  readState, get state from DocumentCompleted Event 
         // via bool value
         bool webbrowserDocumentCompleted = false;
         public void waitWebBrowserToComplete()
         {
           while (!webbrowserDocumentCompleted )
           { Application.DoEvents();  }
           webbrowserDocumentCompleted = false;
         }
    
     }
    
    0 讨论(0)
  • 2020-11-27 03:37

    I think the DocumentCompleted event of the WebBrowser control should get you where you need to go.

    0 讨论(0)
  • 2020-11-27 03:45

    Try the DocumentCompleted Event

    webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted);
    
    void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        webBrowser.Document.GetElementById("product").SetAttribute("value", product);
        webBrowser.Document.GetElementById("version").SetAttribute("value", version);
        webBrowser.Document.GetElementById("commit").InvokeMember("click");
    }
    
    0 讨论(0)
  • 2020-11-27 03:45

    If you are using the InternetExplorer.Application COM object, check the ReadyState property for the value of 4.

    0 讨论(0)
  • 2020-11-27 03:46

    Check out the WatiN project:

    Inspired by Watir development of WatiN started in December 2005 to make a similar kind of Web Application Testing possible for the .Net languages. Since then WatiN has grown into an easy to use, feature rich and stable framework. WatiN is developed in C# and aims to bring you an easy way to automate your tests with Internet Explorer and FireFox using .Net...

    0 讨论(0)
提交回复
热议问题