Results 1 to 15 of 15

Thread: question about why one code works and the other does not

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Jan 2013
    Location
    Overland Park Kansas
    Posts
    183

    question about why one code works and the other does not

    What is the difference between these two? Why is adding an event handler to an Internet explorer window causing the thread to wait for the UI thread?


    Code A:
    -Public WithEvents IE2 As SHDocVw.InternetExplorer to declare my internet explorer object
    -Waits for the original navigate and readystate loop
    -does not do any more navigates or click the login button until after the sub has finished or after the msgbox pops up
    -is not logged in when i expect it to be.

    Code B:
    -Public IE2 As Object to declare my internet explorer object
    -Waits for the original navigate and readystate loop
    -waits for the second loop
    -is logged in when I expect it to be

    CODE A:
    Code:
    Public Module Module1
    Public WithEvents IE2 As SHDocVw.InternetExplorer
    
        Public Sub EOB()
            IE2 = New SHDocVw.InternetExplorer
    
            Dim element As mshtml.IHTMLElement
            Dim doc As mshtml.HTMLDocument
            IE2.visible = True
            IE2.navigate("https://www.treasury.pncbank.com/idp/esec/login.ht")
            Do : Loop Until IE2.readyState = 4
            Do : Loop Until IE2.busy = False
            doc = IE2.document
           'here i plug in the login info
           doc.getElementById("loginFormButton").click()
    
    
    
           
            Do : Loop Until IE2.readyState = 4
            Do : Loop Until IE2.Busy = False
    MsgBox("at this point we should be at the login page but it seems like i'm waiting for the UI thread")





    CODE B:
    Code:
    Public Module Module1
    Public IE2 As Object
    
    Public Sub EOB()
            IE2 = CreateObject("internetexplorer.application")
    
            Dim element As mshtml.IHTMLElement
            Dim doc As mshtml.HTMLDocument
            IE2.visible = True
            IE2.navigate("https://www.treasury.pncbank.com/idp/esec/login.ht")
            Do : Loop Until IE2.readyState = 4
            Do : Loop Until IE2.busy = False
            doc = IE2.document
            'plug in the login info
           
           doc.getElementById("loginFormButton").click()
    
    
    
           
            Do : Loop Until IE2.readyState = 4
            Do : Loop Until IE2.Busy = False
    
            MsgBox("when this pops up i'm logged in")
    
    
    
        End Sub

  2. #2
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,398

    Re: question about why one code works and the other does not

    You wonder why running a loop on the UI thread freezes? Don't ever loop like that, especially as there is a document completed event.

  3. #3

    Thread Starter
    Addicted Member
    Join Date
    Jan 2013
    Location
    Overland Park Kansas
    Posts
    183

    Re: question about why one code works and the other does not

    Quote Originally Posted by ident View Post
    You wonder why running a loop on the UI thread freezes? Don't ever loop like that, especially as there is a document completed event.
    If you read the title of the post it says, and i quote, "question about why one code works and the other does not". I find that, consistantly on these forums, when I have a question the question gets totally ignored and people are suggesting alternate ways of doing something. I know there are alternate ways of waiting for a website to load. I want to know why, when I click the button on one code, the button click event fires instantly and on the other code (where i have public withevents IE) the clicking of the IE button does not happen until after the msgbox pops up or after the sub completes

  4. #4
    PowerPoster
    Join Date
    Jul 2002
    Location
    Dublin, Ireland
    Posts
    2,148

    Re: question about why one code works and the other does not

    Doe sit happen if you omit WithEvents?

    vb.net Code:
    1. Public Module Module1
    2. Public IE2 As SHDocVw.InternetExplorer
    3.  
    4.     Public Sub EOB()
    5.         IE2 = New SHDocVw.InternetExplorer
    6.  
    7.         Dim element As mshtml.IHTMLElement
    8.         Dim doc As mshtml.HTMLDocument
    9.         IE2.visible = True
    10.         IE2.navigate("https://www.treasury.pncbank.com/idp/esec/login.ht")
    11.         Do : Loop Until IE2.readyState = 4
    12.         Do : Loop Until IE2.busy = False
    13.         doc = IE2.document
    14.        'here i plug in the login info
    15.        doc.getElementById("loginFormButton").click()
    16.  
    17.  
    18.  
    19.        
    20.         Do : Loop Until IE2.readyState = 4
    21.         Do : Loop Until IE2.Busy = False
    22. MsgBox("at this point we should be at the login page but it seems like i'm waiting for the UI thread")

  5. #5

    Thread Starter
    Addicted Member
    Join Date
    Jan 2013
    Location
    Overland Park Kansas
    Posts
    183

    Re: question about why one code works and the other does not

    Quote Originally Posted by Merrion View Post
    Doe sit happen if you omit WithEvents?
    [QUOTE=Merrion;4621085]Doe sit happen if you omit WithEvents?QUOTE]


    if I change:

    Code:
    Public IE2 As SHDocVw.InternetExplorer
    
    IE2 = New SHDocVw.InternetExplorer
    to:
    Code:
    Public IE2 As object
    IE2 = createobject("internetexplorer.application")
    The .click of the login button fires when the code tells it to.

  6. #6
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: question about why one code works and the other does not

    It seems that the reason should be obvious, but since I don't do this type of thing I might be mistaken.
    In the first case, you're instantiating the object on the UI thread, so any looping in the UI thread is going to delay other activity of the UI thread.
    In the second case, you're creating a COM object, so it will run independently from the UI thread so will complete its tasks unimpeded.

  7. #7

    Thread Starter
    Addicted Member
    Join Date
    Jan 2013
    Location
    Overland Park Kansas
    Posts
    183

    Re: question about why one code works and the other does not

    How can I add an event handler on a com object?

  8. #8

    Thread Starter
    Addicted Member
    Join Date
    Jan 2013
    Location
    Overland Park Kansas
    Posts
    183

    Re: question about why one code works and the other does not

    Quote Originally Posted by ident View Post
    You wonder why running a loop on the UI thread freezes? Don't ever loop like that, especially as there is a document completed event.
    Oh and I tried using the document completed event and, it turns out, that the document is completed several times before i'm logged in so my readystate/busy loop will wait but the document completed event will misfire

  9. #9
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,043

    Re: question about why one code works and the other does not

    I'm not quite sure what to say about that. You are asking about intercepting events raised by the COM object to redirect them to your app. That may or may not be possible (not something I have ever looked into), but you are tying yourself to COM, which has it's own problems. There is a reason not to use that, but you already jumped on ident for saying that busy loops were bad. What's left to say? You have a pretty good answer to the question you asked. I believe that passel has it right. After all, busy loops don't just freeze the UI, that's nothing more than a symptom. The problem is that they prevent the UI from pumping messages, which makes it look like the UI is frozen, but it really isn't. The messages are queueing, they just don't process until you release the UI to process them. With that being the problem, the answer certainly isn't to move to COM. I've never had great success with that and avoid it where possible. Those snippets make for interesting tests in comparison, but neither one should be viable candidates for solving a real problem. So, is the question now how to solve a real problem, or is it still theoretical?
    My usual boring signature: Nothing

  10. #10

    Thread Starter
    Addicted Member
    Join Date
    Jan 2013
    Location
    Overland Park Kansas
    Posts
    183

    Re: question about why one code works and the other does not

    Quote Originally Posted by Shaggy Hiker View Post
    So, is the question now how to solve a real problem, or is it still theoretical?


    I could write this code on excel in VBA and it would work with the busy loops and application.doevents(). The problem is that I need to interact with a website's popup window. I log into website A and then click a link which opens up website B in a new window.

    I've done this on excel by handling the newwindow event. When I try to handle the newwindow event then my wait for the website to load loops don't work. When I try to handle the newwindow event and use the document completed event the document completed event fires like 5 or 6 times before i'm on the website that I expect to be at.

  11. #11
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,043

    Re: question about why one code works and the other does not

    Busy loops most certainly work. That's why people reach for them so often, but over in the General Developer forum I have a thread where I measured the impact of a busy loop on the current draw of a computer. The fact that you can measure the cost of such a simple piece of code may make it unique. There may be no other three lines of code (other than ones that deal with external hardware devices), which create a measurable jump in power draw using a coarse instrument. Now, that makes no real difference on a multi-core system plugged into a wall. Your electric bill goes up by a thousandth of a penny...big deal. However, you don't want to be doing something like that on a battery powered device, and nobody who uses a battery powered device would want an app that does such a thing. It would be like poking a hole in your battery.

    It's really annoying that the document completed event doesn't fire when the whole document is completed, but that's certainly the case....and getting worse. Back in the day, which isn't so long a go, a web document was just a document. These days, a document is composed of several different things, each of which can complete without the whole thing being complete. Nonetheless, it's the event you want. I feel that there will come a time when the web will be somewhat settled down and more reasonable events will be available, until then, life has to be lived as it is. The thing to do is to handle the DocumentCompleted event DESPITE the fact that it gets raised several times. In the event handler, that is where you check whether the part you want is available. In effect, each time DocumentCompleted is raised, you are asking, "yeah, but is the part I want ready?" The first few times the answer may be no, but eventually it will be yes. That will still be more effective than the busy loop, though it is certainly not all you could want.
    My usual boring signature: Nothing

  12. #12

    Thread Starter
    Addicted Member
    Join Date
    Jan 2013
    Location
    Overland Park Kansas
    Posts
    183

    Re: question about why one code works and the other does not

    Quote Originally Posted by Shaggy Hiker View Post
    Busy loops most certainly work. That's why people reach for them so often, but over in the General Developer forum I have a thread where I measured the impact of a busy loop on the current draw of a computer. The fact that you can measure the cost of such a simple piece of code may make it unique. There may be no other three lines of code (other than ones that deal with external hardware devices), which create a measurable jump in power draw using a coarse instrument. Now, that makes no real difference on a multi-core system plugged into a wall. Your electric bill goes up by a thousandth of a penny...big deal. However, you don't want to be doing something like that on a battery powered device, and nobody who uses a battery powered device would want an app that does such a thing. It would be like poking a hole in your battery.

    It's really annoying that the document completed event doesn't fire when the whole document is completed, but that's certainly the case....and getting worse. Back in the day, which isn't so long a go, a web document was just a document. These days, a document is composed of several different things, each of which can complete without the whole thing being complete. Nonetheless, it's the event you want. I feel that there will come a time when the web will be somewhat settled down and more reasonable events will be available, until then, life has to be lived as it is. The thing to do is to handle the DocumentCompleted event DESPITE the fact that it gets raised several times. In the event handler, that is where you check whether the part you want is available. In effect, each time DocumentCompleted is raised, you are asking, "yeah, but is the part I want ready?" The first few times the answer may be no, but eventually it will be yes. That will still be more effective than the busy loop, though it is certainly not all you could want.
    My jobs run on pc computers so I perfer the readystate loops. The problem is that the readystate loop stops functioning as intenended when I want to handle the IE newwindow event. How can I handle that event outside of my UI thread?

  13. #13
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,043

    Re: question about why one code works and the other does not

    Actually, you prefer the busy loops (I assume that's what readystate means), and you happen to be running on a PC, so the cost to the system doesn't matter, but that's just a detail.

    The UI thread is where all the messages are handled because that is where the message loop exists. I believe you could make other message loops, but you'd find that FAR harder than getting rid of the busy loops, if it is even possible. Therefore, one alternative would be to perform the busy wait in a background thread. There may be a different way if you are targeting framework 4.5, though I have never tried it. It's kind of the same thing, though, as it would perform the busy wait in a task, which may or may not run on a different thread at the discretion of the OS.
    My usual boring signature: Nothing

  14. #14
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: question about why one code works and the other does not

    I might not understand your needs, and I'm not familiar with having to deal with web pages, but generally you don't want to hang up the GUI thread, so you need to process application state information in some kind of event.
    It seems like the DocumentCompleted event is the place it should be done.
    It would seem like since you have two conditions that you are waiting on (readyState = 4 and busy=false), you could check for these conditions in the DocumentCompleted event.
    If the conditions aren't met, then perhaps this is not the final DocumentCompleted event, so you wait for the next one to check again.
    If for some reason, the final DocumentCompleted even comes before those two conditions are satisfied, then another convenient event for periodically checking for some condition (polling), would be the timer tick event.
    Set up a "state" machine in the timer (or called from the timer) to test that expected conditions are met, possibly do some processing and then look for the next state (step) in the process.
    Moving "Loop" logic code into periodic event of the timer is the way to poll for conditions over time without hanging the code and preventing events from being processed.
    A possible example, based on what you've posted:
    Code:
      Public WithEvents IE2 As SHDocVw.InternetExplorer
      Dim WaitState As Integer
      Dim element As mshtml.IHTMLElement
      Dim doc As mshtml.HTMLDocument
    
      Public Sub EOB()
        IE2 = New SHDocVw.InternetExplorer
    
        IE2.visible = True
        IE2.navigate("https://www.treasury.pncbank.com/idp/esec/login.ht")
        WaitState = 1
        Timer1.Interval = 1
        Timer1.Start()   'Start the state machine for EOB login
      End Sub
    
      Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
        Select Case WaitState
          Case 1
            If IE2.readyState = 4 Then
              WaitState = 2
            End If
    
          Case 2
            If IE2.busy = False Then
              doc = IE2.document
              'here i plug in the login info
              doc.getElementById("loginFormButton").click()
              WaitState = 3
            End If
    
          Case 3
            If IE2.readyState = 4 Then
              WaitState = 4
            End If
    
          Case 4
            If IE2.busy = False Then
              MsgBox("when this pops up i'm logged in")
              'Perhaps at this point clean up by disposing of doc, or setting it to nothing if it is no longer needed
              WaitState = 0  'no longer processing EOB
              Timer1.Stop()  'stop the timer from firing
            End If
        End Select
    
      End Sub
    End Class

  15. #15
    Bad man! ident's Avatar
    Join Date
    Mar 2009
    Location
    Cambridge
    Posts
    5,398

    Re: question about why one code works and the other does not

    Ok let's think about this for a little bit because it's getting silly. You would not add a timer to handle such things. You don't want to use SHDocVw.InternetExplorer at any rate, COM based browser control is what you should focus on. Plenty of examples on MSDN.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width