async streams interactive communication

mterveen

Member
Licensed User
Longtime User
is there a simple way to send info via async streams, wait for a response, then send more info? i need to send a byte via bluetooth, wait for a byte to be returned, and continue this send/receive routine until the user stops the process. or is there a better stream to use? the bytes can range from 0 to 255.
 

mterveen

Member
Licensed User
Longtime User
i had initially tried that but could not get it to work with async. i had set up a process-global variable called AsyncBytesReceived. in the async_newdata routine i updated the variable with the cumulative bytes received. in the main routine i would set the global variable to 0, send the bytes, then loop until the global variable equaled the number of bytes i was wanting. it seemed that the global variable would never get updated with the bytes so the loop would never finish. did this main sub loop block the async receive thread from updating the variable?!? or is there something i'm doing wrong?
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
then loop until the global variable equaled the number of bytes i was wanting.
This is the problem. Such a loop doesn't let the process to handle incoming messages.

Instead you should add the bytes in NewData event and when enough bytes were collected you should call the "next step" sub.

If you have control on both sides of the connection then you can use prefix mode to simplify things.
 
Upvote 0

mterveen

Member
Licensed User
Longtime User
so, even though the async newdata event is on a separate thread, a loop in the main thread will suspend its functioning? i don't understand, or doesn't async newdata run on a separate thread?

the problem with using the async newdata event is that the responses back could be several things, from responses to actual data bytes. for example, in my case my external bluetooth adapter will send back an "Aok" response if the sent command is successful. however, most of the commands respond with that so if would be virtually impossible to provide all possible branches to the appropriate subs in that event. also, sometimes a byte is sent to confirm a setting on the external microcontroller. it would be very hard to differentiate in that sub if it is a "real" data byte or a confirmation byte.

so, if i understand correctly, there is no way to "sleep" a sub in the main thread while waiting for other threads to complete? if there is, please link me to it and i will be most grateful. another example would be the serial connect subs. i would rather pause the main sub i am working on until the connection is successful and then continue from that point versus having to put the subsequent code in the serial connect sub.

for now, i am able to achieve what i need using the standard input and output stream functions, though very poorly from a programming flow point of view.
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
AsyncStreams does work in the background. However when new data arrives it delegates it to the main thread. Your code runs in the main thread. Android doesn't allow you to pause the main thread. After several seconds it will show an "Application not responding" dialog.

You should store the current state in a global variable. It shouldn't be too difficult.
 
Upvote 0

mterveen

Member
Licensed User
Longtime User
gotcha - i hate asking newbie questions cause when u look back at it a couple days later you realize just how dumb it was!!!

also, have not thanked u nor your support crew for this wonderful product.

is there a specified time out on the blocked async read in the background thread or is it infinite?
 
Upvote 0

GiovanniPolese

Well-Known Member
Licensed User
Longtime User
Communication with aspx

I have the following scenario:
1) a classic asp and an asp.net programs on a site
2) I developed a b4a application communicating with them
3) b4a program issues exacly same calls than the browser (obviously)
a call may be: http://www.mysite.it/folder/program.asp(x)?parameters
4) b4a applications is developed based on tutorial examples: a variale hc is declared as HttpClient and a req as HttpRequest in Process_Globals. Then I do: req.Initialize(QueryString) and hc.Execute(req,1) and after I wait asyncronous response. (Actually the answer string is written on a temporary file, during ResponseSucces event and read from the temporary during Sream_Finish. This should be of no importance, because when program is used with classic asp it works fine).
5) doing a simple browser call I get the expected result, which is a line of text in the browser (as documented in screen_1.png)
6) issuing rigorously same call with b4a and classic asp as a counterpart, I get same result like the browser (not shown, but problem concerns differences between the answers to browser and to b4a calls).
7) issuing same call with b4a and asp.net program as a counterpart I get a completely different answer, which seems to be the page of "request", just like the answer is an untitled browser page containing the request and no answer. (see screen_2.png)
8) screen shots of what happens are available at:

www.galileo2000.it/download/screen_1.png

and

www.galileo2000.it/download/screen_2.png

In screen_1.png I show the call issued by the browser, its answer and the call issued by b4a during debugging, while in Screen_2.png I show the answer of the site, captured during Stream_finish.
9) In the asp.net program only Response.Write of data are done, as browser result shows. If other response content is sent back by asp.net program, it has to be implicit.
Thanks in advance to anybody that has any idea of what happens..
 
Upvote 0

GiovanniPolese

Well-Known Member
Licensed User
Longtime User
Server access

No, I haven't such type of access you mean, I guess. I just published the files, but I cannot see what happens server-side during asp.net execution. The strange thing is that classic asp and browser behave exactly same way, i.e. b4a gets only the line displayed by the browser, when the response is managed by asp. Also notice that the Response got by b4a is not the correct answer plus some header/footer/whatelse, but a sort of echo of the requesting page. I will prepare an adaptation of one of your tutorial examples and post it, so I hope you can see what happens. On the other side I will put an asp and an aspx code and I will post them too. Only confirm me that this will be useful, because if you don't think that this can help, I will try another way, with a php counterpart... hoping... (By the way perharps I will resolve myself, during experiment, if it depends on my code.) Let me know asap whether to do this or not.
Thanks and best regards
Giovanni
 
Upvote 0

GiovanniPolese

Well-Known Member
Licensed User
Longtime User
Ok

The issue is not whether HttpClient sends what I give it or not. The problem is that I send same string than in the case of a Browser call and, with b4a program, I don't get the answer but something else. If code on server side were wrong, it should wrongly answer to direct browser call too, or, anyway, give an answer composed but some overhead plus the required line. The only suspect I have is that the HttpClient inquiry is not well formed and, while classic asp overcomes some ill conditioning, asp.net doesn't. Infact I wrote that classic asp and b4a "talk" without problems.. Is there any different way to issue the Http request, other than the way explained in currency-converter? (actually I used this simpler tutorial, as a basis for my application)
Thanks anyway
 
Upvote 0

GiovanniPolese

Well-Known Member
Licensed User
Longtime User
By the way

By the way I confirm that b4a gets php answers correctly. So the problem is confined to answers given by asp.net. I'll further investigate and if I'll get any new, I will post it.
 
Upvote 0

GiovanniPolese

Well-Known Member
Licensed User
Longtime User
Communication

There are some issues to avoid problems when using VisualStudio asp.net projects to manage the connection with b4a. My application is, functionally, a sort of WebService. B4a issues the HttpRequests and gets back the Responses generated by the asp(x) counterpart, which manages a data base. What I experienced is that my problems where due to the use of codebehind and responses generated inside the Page_Load event. All processing is done inside the aspx.cs codebehind file, and in my aspx file there were no explicit calls to the code behind. This mechanism, implicitly relying on Page_Load, gave me the problems. I empirically resolved substituting the Page_Load function with a function that is called "explicitly" inside the aspx. I don't know whether this solution is the best. For my use, it works. If somebody needs, I can give further details. That's all folks..
 
Upvote 0

VBAPro

New Member
Licensed User
Longtime User
Hi Erel,


This is my first post on this forum. First I would like to thank you very much for building this whole thing. I am a freelance VBA developer - I hate Java, but I love Visual Basic, so in Basic4Android I feel right at home.

Also, I apologise in advance for the length of my post. I have a fairly simple problem, actually.

I am developing an interactive Android game where two devices are constantly sending simple textual messages back and forth via Bluetooth. I am not using InitializePrefix, and I am considering trying AsyncStreamsText, but it might be unnecessary.

Here is my situation: when both devices are in the menus part of the game, where the users have the opportunity to change various settings which affect the game; and I connect the devices to each other via Bluetooth (which I 'borrowed' from your Bluetooth chat example and I integrated it in my in-game menus), changing one setting on one device changes the same setting appropriately on the other device almost instantaneously. So the two-way communication works, and that's great. Then I hit the 'PLAY' button on either device, and both devices load the gameplay screen and start playing the game. So that's excellent.

However, once I start the actual game, which works in real-time, I am experiencing the exact issue which you described above as
You will need to track the state with a global variable until the communication is done.
and
AsyncStreams does work in the background. However when new data arrives it delegates it to the main thread. Your code runs in the main thread. Android doesn't allow you to pause the main thread. After several seconds it will show an "Application not responding" dialog.
You should store the current state in a global variable. It shouldn't be too difficult.

Namely, while the real-time part of my game is running, all of the text messages get queued up on both devices. When the real-time part is done running, the devices start reacting to the text messages from each other, and there are a lot of them because they got queued up on both sides. This was supposed to occur during the real-time gameplay, not after it.

Now, I understand that Android doesn't allow me to pause the main thread in order to execute the code which needs to run when new data arrives. That makes sense to me.

However, I did a test with ToastMessageShow - I put a ToastMessageShow at the beginning of the AStream_NewData event, and it never runs during the real-time portion of the gameplay.

So, my question is: how do I do this? How do I track the state with a global variable? I understand that in my main loop, at the end of each iteration of the loop I need to check that global variable, but how?

So 1) What exactly do I need to track the state of?, and 2) what do I put in the global variable?

I cannot read the Buffer as part of the loop in the main thread, because Buffer() is passed to the AStream_NewData event and I have no access to the Buffer outside of the AStream_NewData event - and the AStream_NewData event doesn't fire up during the main loop, but in queues up instead and fires all of them after the main loop is done.

Could you please give me some sample code where this is handled, so that the main loop checks the global variable at the end of each iteration, and I also needs to see what gets put into the global variable and when.

(offtopic) Also, I just wanted to make a small suggestion for future improvements. When using the Find & Replace string feature in Basic4Android, I want to do a 'Replace All' within one sub, so I select that entire sub and do the replace, and it works the way I want it to.

My question is - could you please add check boxes or radio buttons to the Find dialog box so that the user could specify whether they want to "Replace <this> with <that>" within the current sub, within the current module, or within the current project?


Thanks!
 
Upvote 0
Top