简体   繁体   中英

The Code Works Fine When Debugging, But it Doesn't work when it runs without Debugging

  string entry = Titleentry.Text;
        webBrowser1.Navigate("http://www.bookdepository.com/search/advanced");

        //HtmlElementCollection bookCollection;

        while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
        {
            Application.DoEvents();
        }

        HtmlElementCollection bookCollection = webBrowser1.Document.GetElementsByTagName("input");
        foreach (HtmlElement curElement in bookCollection)
        {
            if ((curElement.GetAttribute("id").ToString() == "searchTitle"))
            {
                curElement.SetAttribute("value", entry);
            }
        }



        HtmlElementCollection filterCollection = webBrowser1.Document.GetElementById("filterSortBy").GetElementsByTagName("option");
        List<HtmlElement> filterList = new List<HtmlElement>();
        foreach (HtmlElement filterItem in filterCollection) { filterList.Add(filterItem); }
        HtmlElement filterElement =
          (HtmlElement)filterList.Where(filterOption => filterOption.GetAttribute("value").Equals("price_low_high", StringComparison.InvariantCultureIgnoreCase)).SingleOrDefault();

        if (filterElement.GetAttribute("value").Equals("price_low_high"))
        {
            filterElement.SetAttribute("Selected", "price_low_high");
            filterElement.InvokeMember("click");
        }

        bookCollection = webBrowser1.Document.GetElementsByTagName("button");

        foreach (HtmlElement curElement in bookCollection)
        {
            if (curElement.GetAttribute("id").Equals("searchSubmit"))
            {
                curElement.InvokeMember("click");
            }
        }
        while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
        {
            Application.DoEvents();
        }

        MessageBox.Show("Loaded");

        System.Timers.Timer myTimer = new System.Timers.Timer(5000);
        myTimer.Enabled = true;
        myTimer.Start();
        myTimer.Stop();

        if (webBrowser1.ReadyState == WebBrowserReadyState.Complete) //from here on the code doesnt work.
        {
            HtmlElementCollection avCollection = webBrowser1.Document.GetElementById("filterAvailability").GetElementsByTagName("option");

            List<HtmlElement> avList = new List<HtmlElement>();
            foreach(HtmlElement avItem in avCollection)
            {
                avList.Add(avItem);
            }

            HtmlElement avElement =
                (HtmlElement)avList.Where(avOption => avOption.GetAttribute("value").Equals("1")).SingleOrDefault();

            if (avElement.GetAttribute("value").Equals("1"))
            {
                avElement.SetAttribute("Selected", "1");
                avElement.InvokeMember("click");
            }

            bookCollection = webBrowser1.Document.GetElementsByTagName("button");
            foreach (HtmlElement curElement in bookCollection)
            {
                if (curElement.GetAttribute("id").Equals("searchSubmit"))
                {
                    curElement.InvokeMember("click");
                }
            }
        }

here is the whole code. I tried setting the delay with timer thinking because it is reacting too fast but the timer is also not working so im not sure what the problem could be.

the code that doesnt work is suppose to create the avList with 3 counts and choose the value 1. the value 1 represents the In Stock availability of the website.

when running without debugging it seems to completely ignore the code written in the if condition.

thanks

Ok, the issue looks to be with the way you setup your code. You are trying to do things one after the other which is yielding some strange results. It is best to allow the API (WebBrowser) tell you what is going on rather than trying to query it until it is done.

Having a loop to check "are you done yet?" is considered back practice because it blocks your code and occupies the processor with a wasteful wait loop.

What you need to do, is look through the documentation for the WebBrowser API and figure out how the WebBrowser communicates back to the calling class. C# takes a huge advantage of Events and Delgates, so my suggestion is to look to see if there is an event for what you are looking for. A quick search came up with:

http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.ondocumentcompleted.aspx

This is far move manageable approach than to spin a while loop until the condition is met. Let the API inform you when it's done and then you can decide what to do with it. As for your events, here is an example of how the event is wired:

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.onkeydown.aspx

so you do not have to check for them in a loop, eating up processing time.

Also, since your in the .NET world you have access to linq. You don't have to write out your loops in order to find something. For instance:

    //Note: I have not tested this code, but this is close to what it should look like
    bookCollection.where(x => x.GetAttribute("id").ToString() == "searchTitle")
              .ForEach(x => x.SetAttribute("value", entry));

I cannot vouch for how fast this is, but LINQ tends to clean up the logic for looping and searching.

=====================================

If you insist of having your code, the issue arises from

     webBrowser1.ReadyState

which is no longer in the "Complete" state. However, your while loop already checks for this condition right above, so you can just remove the IF statement. The reason I told you that you have an iffy while loop is for this exact reason. The enum value is there so that you can query the WebBrowser process while it is still processing. This is useful in multithreaded software. However, my guess is that the flag is flipped to

   webBrowser1.ReadyState == WebBrowserReadyState.Complete

right before the page is displayed. That would explain why your while loop picks up on it and exists out. Now, the issue is that it will probably flip the enum to Uninitialized because it is finished loading the page and has disconnected the socket connection. This would put it into the Unintialized state. This API relies on a state machine pattern and the sequence of the states are are probably different from what you think they are. Here is more information about state machine:

Simple state machine example in C#?

I hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM