Using Asynchronous GetXmlHttpObject() vs threads

Discussion in 'Questions (Windows Mobile)' started by aerohost, Jul 10, 2008.

  1. aerohost

    aerohost Member Licensed User

    Hi All, I'm having trouble with my new application because it uses the http module to received data over the net.

    Because it is a synchronous protocol, my whole program freezes up while it does this and it becomes problematic, interfering with what the user may be doing on the device, especially if the internet connection is of poor quality.

    What I really need is a way of putting this process into the background, so that it doesn't interfere with the user doing other things.

    Is there a way to do this with threads, or by using some of the new Ajax techniques?

    Thanks, Adrian
     
  2. agraham

    agraham Expert Licensed User

  3. aerohost

    aerohost Member Licensed User

    Thanks, that looks like the solution I've been hoping for, I'll definitely give it a whirl.

    Just wondering, what do you think about using Ajax techniques as an alternative - is this even possible with b4ppc?

    Thanks, Adrian
     
  4. agraham

    agraham Expert Licensed User

    As I understand it, and I'm not too good on Webby stuff, Ajax is a web server/browser interaction that requires client side scripting. I could give a long complicated answer but the short answer is it is neither appropriate for nor possible with B4ppc.

    As a matter of background B4ppc is single threaded and historically byte-code interpreted. More recently it has grown a fully compiled capability. It deliberately does not provide asynchronous methods in it's libraries as this would be complicated to implement in a byte-code machine and a complication for the programmer in it's role as a simplified rapid development environment.

    My Threading library, which only actually threads on optimised compiled apps, is one of my subversive attempts to make things more complicated :) by letting the synchronous operations of B4ppc effectively become asynchronous. It allows asynchronism without getting into the complications of setting callbacks that .NET fully asynchronous operations demand and which are not supported by B4ppc.
     
  5. aerohost

    aerohost Member Licensed User

    Thanks! That's a really good answer, imho, just what I was trying to understand ... onward ho to the thread library it is ...

    Regards, Adrian :sign0087:
     
  6. aerohost

    aerohost Member Licensed User

    Hi Andrew, I tested your excellent thread library with the 'ThreadTest.sbp' example you provided.

    The thread that displayed the counter 0-1000 seemed to work well, so I then replaced just that section with an http page call. I then disabled my net connection and found that it behaved the same as ever and locked up the program until the timeout completed, then it just stopped, ignoring the ErrorLabel.

    Any idea why that wouldn't work?

    Tks, Adrian
     
  7. agraham

    agraham Expert Licensed User

    As long as you had optimised compiled it then no! Can you post the code you tried?
     
  8. aerohost

    aerohost Member Licensed User

    Hi Andrew, thanks for your reply. I put the changed sub at the bottom, nothing else was altered.

    So I think the clue here is your 'optimised compiled' statement. I am only testing it from the IDE, without making an exe. Is that creating problems, in other words, do I have to make an exe to test it properly?

    Also, I'm confused by the 'legacy mode' message box I keep getting when run from the IDE. Does that mean I don't have all the required up-to-date stuff (I thought I had the latest versions of everything), or do I just get that because I'm running from the IDE?

    Thanks, Adrian
    ---------------------
    Sub ThreadCode
    ErrorLabel(ThreadCodeErr1) ' if abort is used to stop a thread an (intended by .NET) error occurs

    'try to fetch data from server
    Response.New1
    Request.New1("http://myURL")
    ' Msgbox(url)
    'This line calls the server and gets the response.
    Response.Value = Request.GetResponse

    string = Response.GetString 'Get the Response string.
    'did we get data? if we hit next line, we did
    Msgbox(string)
    tb1text = "ok"

    ' For i = 1 To 1000
    ' For j = 1 To 1000
    ' k = i + j
    ' Next
    ' tb1text = i
    ' Thread.FireThreadEvent ' events work for testing even if not running on a separate thread
    ' Next
    ThreadCodeErr1: ' ignore any error
    tb1text = "not ok"
    'Return k ' stops unused variable error
    End Sub
     
  9. agraham

    agraham Expert Licensed User

    The second paragraph of Overview in the help
    Threading does not work in the IDE as that is a byte-code environment (known as legacy mode to us cognoscenti :)) as is non-optimised compilation. True threading will only work in an optimised compiled app. However you can debug a threaded app (sort of) in the IDE and if you read the demo app closely it has some pointers in there as to how. To debug an optimised compiled app you can try the Watcher from my debug library which can look inside a running optimised compiled app. http://www.basic4ppc.com/forum/additional-libraries/2328-debug-library.html

    That's the library warning you that threading is not available in the legacy environment.
     
    Last edited: Aug 18, 2008
  10. aerohost

    aerohost Member Licensed User

    Hi Andrew, ok, thanks very much for your feedback. I'm using your 'ThreadTest.sbp' example to try and understand how this works.

    In the 'Sub ThreadCode' you have the loop that counts to 1,000 you have this code:

    For i = 1 To 1000
    For j = 1 To 1000
    k = i + j
    Next
    tb1text = i
    Thread.FireThreadEvent
    Next

    I'm presuming this is the actual background task you are running in a thread to demonstrate that the user can still do other things on the form while the text box displays the updated value. This works fine for me - it's a good way to demonstrate events running in a background thread.

    So, I'm trying to substitute that code with a simple http request, as follows:

    Response.New1
    Request.New1("myURL")

    'This line calls the server and gets the response.
    Response.Value = Request.GetResponse
    Thread.FireThreadEvent

    If I'm connected to the net, it works fine, but when I disconnect from the net, the whole form is stalled and you can't do anything else. I have put a drop-down listbox on the form as an example of doing something on the form while the internet is being accessed, and it is frozen while the thread attempts to connect to the non-existent internet connection.

    This is the essence of my problem: I need the form activity to continue, when the http request is made, even if the internet connection is broken.

    I'm wondering if I have the 'Thread.FireThreadEvent' statement in the wrong place?

    I haven't changed anything else, except in the initialization sub:

    #Region Create and start a thread

    Thread.New1(B4PObject(1))
    If Optimising Then
    Thread.Start("ThreadCode") ' returns true if started, false if not
    Else
    'ThreadCode
    End If

    #End Region

    I commented out the ThreadCode line so nothing would happen until I pressed the start button because the legacy message was getting in the way, and I needed to be able to clear that first to test it properly?

    So can you see any reason why the http request jams up everything?

    Thanks, Adrian
     
  11. agraham

    agraham Expert Licensed User

    I don't understand this. Optimising is a global variable and in the demo it is set true, so unless you have set it false that commenting out should do nothing. You shouldn't be getting a legacy message anyway if you are running an optimised compiled app.
    You are optimising compiling this to run it aren't you? I can't easily dump my network connection but I've run the following code as you have described, adding a line to see the response and a duff URL that causes a couple of seconds delay before GetResponse returns. Pressing the Join button reports that the thread is running showing that my user interface is alive during this time as I would expect.
    Code:
    Response.New1
    Request.New1(
    "http://www.dac")
    'This line calls the server and gets the response.
    Response.Value = Request.GetResponse
    tb1text = Response.GetString 
    ' added to see the response
    Thread.FireThreadEvent
     
  12. aerohost

    aerohost Member Licensed User

    ok, so maybe I'm not understanding this correctly. When you say

    "You are optimising compiling this to run it aren't you?"

    do you mean I have to compile it into an exe for it to work properly? I'm confused because your 1000 loop example seems to run fine in the IDE as a background task when I test it.

    Tks, AB
     
  13. agraham

    agraham Expert Licensed User

    Exactly! As I noted previously threading is not possible in the byte-coded legacy environments of the IDE and non-optimised compiled exes. That's why I implemented the legacy warnings.

    It runs, but not as a background task and not without modifying my demo code. Set the global variable Optimising to false and it runs under the IDE. This demo is structured to show how code could be tested in the IDE without threading and then run compiled as a threaded app.

    Please read through the demo app and the help file line by line. My technical writing tends to be terse and succinct and every word is normally there for a purpose so you can't just skim my stuff and expect to understand what's going on.
     
  14. aerohost

    aerohost Member Licensed User

    Hi Andrew, thanks I'll give it a try. Honestly, I read and re-read your instructions, but I was confused because it appeared to run in the IDE, so I thought I was mis-interpreting them.

    What I didn't understand was that although it is running, it isn't running as a thread until the program is compiled. So, my http request was running, but not as a thread either, and it was jamming everything up as usual.

    Thanks for taking the time to clarify this because, frankly, if I can't get this to work, my project is dead, and I will have wasted hundreds of hours. If I can get this working, your threading will save the day! I'll let you know ...

    Regards, Adrian
     
  15. Erel

    Erel Administrator Staff Member Licensed User

    There are plans to add asynchronous communication support to the HTTP library.
    However it will only be released after the next version.
     
  16. aerohost

    aerohost Member Licensed User

    Hi Andrew, that's good news from Erel about adding asynchronous communication support in the next release. But, I'd still like to get this working as I can see threads are very useful, not just for this.

    I compiled it as we discussed, and it appears to be working. But, when I disable the network connection, the thread appears to just stop after it timesout, and it doesn't display the 'not ok' message in the textbox. In other words, it doesn't seem to get to the error routine - any idea on that?

    Tks, Adrian (code below)

    Sub ThreadCode
    ErrorLabel(ThreadCodeErr1)

    'try to fetch data from server
    Response.New1
    Request.New1("myURL")

    'This line calls the server and gets the response.
    Response.Value = Request.GetResponse
    Thread.FireThreadEvent

    'did we get data? if we hit next line, we did
    Msgbox(Response.GetString)
    tb1text = "ok"
    Return

    'program flow should go here if there's no internet found or other error
    ThreadCodeErr1:
    tb1text = "not ok"
    Return

    End Sub
     
  17. agraham

    agraham Expert Licensed User

    I'm surpised it does display the OK message in the testbox! Does it? If you are still using the structure of the demo then the textbox is updated by the ThreadEvent and your FireThreadEvent is in the wrong place. You also have a superfluous Return in there that is doing no harm. It should look like this.
    Code:
    Sub ThreadCode
      ErrorLabel(ThreadCodeErr1)

      
    'try to fetch data from server
      Response.New1
      Request.New1(
    "myURL")

      
    'This line calls the server and gets the response.
      Response.Value = Request.GetResponse

      
    'did we get data? if we hit next line, we did
      tb1text = "ok"
      
    Thread.FireThreadEvent ' update textbox
      Msgbox(Response.GetString)
      
    Return

      
    'program flow should go here if there's no internet found or other error
    ThreadCodeErr1:
      tb1text = 
    "not ok"
      
    Thread.FireThreadEvent ' update text box

    End Sub
    The ONLY GUI thing you can do within a thread is to display a messagebox. Anything else must be done by a ThreadEvent or DebugEvent.

    Note he said after not in -possibly big difference.
     
  18. aerohost

    aerohost Member Licensed User

    Hi Andrew, ok, that works perfectly now.

    You said: "I'm surprised it does display the OK message in the testbox! Does it?"

    The 'ok' seemed to work, but the 'not ok' didn't, but it's all fixed now.

    Just so you have the bigger picture, this problem of 'no internet, program jams up' didn't appear during my lab testing because it was always connecting.

    It wasn't until I started driving around in a marginal area with my mobile moving in and out of 'no service' that I realized my program wouldn't work because of the halt on any other lookup activities (with data already on the phone) during timeouts.

    It's the mobile front end for a larger database application:

    Access Database Demonstration Online - SQL Alternative

    One final question, if you will: I don't understand what these routines are about:

    Demonstrate locking a resource
    Resource locking routines

    I'm sure I will over time, but for now I want to distill this down to the minimal amount of code I actually need for this particular purpose. So, do I actually need those items above?

    Thanks again for all your patience, and for saving the day with your threads!

    Regards, Adrian
     
  19. agraham

    agraham Expert Licensed User

    They are useful when two threads need to update or use the same resource such as a global variable or a Serial Port or some other resource that only supports a single method of access. The "Thread safety" section in the "Thread pitfalls" topic of the help tries to explain this.

    You probably don't need them for the time being but if you get, for example, variables set to unexpected values or apparently not being set then see if that variable is being used in both the main program and a thread, or in two threads. If it is then consider the result of both threads trying to use it at once (one reading, one writing is usually but not always OK). In that case you may need to lock the variable before using it and unlock it after.
     
  20. aerohost

    aerohost Member Licensed User

    Hi Andrew, great, got it, thanks again!

    Regardos, Adrian
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice