Android Question What's the preferred way to do a wait?

Troberg

Well-Known Member
Licensed User
Longtime User
Occasionally, especially in some GUI cases, one wants to wait a short while before continuing. For example:

Do something
Show a message
Wait 3 seconds
Show another message
Wait 3 seconds
Clear messages

In this case, it's messages, but it's not limited to that.

What is the preferred method om implementing such a wait. Sure, I could use a timer, but that would either lead to a very awkward partitioning of the code (especially if large piles of variables are needed both before and after the wait) or to the use of a DoEvents-loop, which will drain the battery.

So, what is the proper way of doing this?
 

Mrjoey

Active Member
Licensed User
Longtime User
B4X:
public void Initialize(BA ba, String EventName) {
        this.ba = ba;
        this.eventName = EventName.toLowerCase(BA.cul);
        }
u can find ba.wait(time)
 
Upvote 0

RandomCoder

Well-Known Member
Licensed User
Longtime User
Personally I would use a timer. Enable the timer instead of using a loop and with each tick event display the desired message, you only need one variable to keep track of which message to display. On the tick event after the last message has been displayed disable the timer and callsub or callsubdelayed to summon your next bit of code.

Regards,
RandomCoder
 
Upvote 0

Troberg

Well-Known Member
Licensed User
Longtime User
In the message case, it would be trivial to, say, implement a message queue read by a timer. However, in the generic case, it's not so easy. Think of it like this:

Do lots of stuff
Wait (perhaps to avoid choking the network/database/something else)
Continue doing stuff with the stuff you worked on earlier

In this case, a timer becomes more awkward. You may have huge data structures you are working on, and it's awkward to just pick up and continue in a new context.

It's not something you need every day, but occasionally, it's useful.
 
Upvote 0

RandomCoder

Well-Known Member
Licensed User
Longtime User
I would still advise to use a timer. When doing part of a large task, set a variable to signal task in progress (the variable could state which task, or which part of the task) and start the timer. Use the tick event to check your program to see if the values/files or whatever it is your waiting for has been updated. Then stop the timer and use the variable set earlier to decide what to call next.
Event driven programming is quite new to me, I'm use to using Do While(1) but that just is not the way anymore. Using events properly can really reduce battery consumption and prevent the phone from becoming unresponsive.

Regards,
RandomCoder
 
Upvote 0

sirjo66

Well-Known Member
Licensed User
Longtime User
I think that the use of a timer is the better solution, but.....

If you need to wait few seconds you can also use a do-loop, and wait until DateTime is over a value.

For example:
B4X:
Sub WaitFewSeconds(MilliSeconds As Int)
Dim TimeOut as Long

TimeOut = DateTime.Now + MilliSeconds
Do Until DateTime.Now > TimeOut
    DoEvents
Loop

End Sub

Sergio
 
Upvote 0

RandomCoder

Well-Known Member
Licensed User
Longtime User
If you need to wait few seconds you can also use a do-loop, and wait until DateTime is over a value.

I would guard against use of such practice's, please see the android docs with regard to ANR (Application Not Responding) faults...http://developer.android.com/training/articles/perf-anr.html
It appears that any delay over 5s can potentially cause the fault to appear. It also deems that any delay of over 100 to 200 ms on the main thread can make an app feel unresponsive.

I'm not a professional android programmer and this is just my humble opinion, you can of course do it however you want to. It's your program after all ;)

Kind regards,
RandomCoder
 
Upvote 0

Troberg

Well-Known Member
Licensed User
Longtime User
A variant on the DoEvents loop is to kick off a timer, and in timer event disable the timer. Then just start the timer and loop until it's disabled. I suffers from two problems, though:

* Inefficient power use. A tight DoEvent loop spikes CPU usage.
* Risk of unresponsiveness.

Usually, the OS supplies some kind of Wait API, but I'm new to Android and don't know what it offers.
 
Upvote 0

Troberg

Well-Known Member
Licensed User
Longtime User
I suppose I have to.

The thing is, this is a big number crunch, so it's not a single variable I need to keep, it's at least half a dozen multidimensional arrays of objects. There simply is no "natural split point", which is why I asked if there was some kind of call one could use.
 
Upvote 0

MaFu

Well-Known Member
Licensed User
Longtime User
You should explain more in detail what your app do. Then we can eventually recommend the most reasonable way.
Maybe a FIFO stack combined with a timer is a proper solution. Each stack element contains the task to do and the start time (relative to the last task).
 
Upvote 0

thedesolatesoul

Expert
Licensed User
Longtime User
I suppose I have to.

The thing is, this is a big number crunch, so it's not a single variable I need to keep, it's at least half a dozen multidimensional arrays of objects. There simply is no "natural split point", which is why I asked if there was some kind of call one could use.
You should do heavy operations like that on a background thread.
Have a look at the Threading library.
 
Upvote 0

Troberg

Well-Known Member
Licensed User
Longtime User
To make a long story short, it's a couple of millions of measurements in, a lot of mathematics, resulting in some tens of thousands processed numbers out which is stuffed into a server side database. I've noticed some choking which leads to lost packages (unsure at the moment if it's network or server side database, but a short pause every once in a while solves it).

However, this is one case. It's not the first time I've had this need over my career. Often, one can redesign the code a bit to use a timer, but in a few cases, it just becomes very awkward.

I'll have a look at the threading library. I'm unsure if it will do here, as I also display data on screen as I work, but it's certainly something I need in other cases.
 
Upvote 0

evansus

Member
Licensed User
Longtime User
Somewhat related question
If I have a Timer_Tick event and put code (including subroutine calls) in this event does this code run in its own thread?
I also want to invoke the ability to run large calculations in the background at regular intervals (once every 3 seconds or so) and then update the GUI. I know I can use the threading library as long as it does not interface with the GUI but should I make the call to the new thread from within a timer tick event or is this going to cause problems?
 
Upvote 0

Troberg

Well-Known Member
Licensed User
Longtime User
If you can split up the work in small enough chunks, using a timer can provide a very "thread-like" behavior without having to resort to threading.
 
Upvote 0

RandomCoder

Well-Known Member
Licensed User
Longtime User
We should also mention that often you don't even need to use a timer. If the structure/flow of your program allows it, you may be able to break down the operations into small chunks. Each triggering an event to move onto the next operation.

For example, my UPNP control point has no idea what is on the network. It sends out a search request and receives responses from all the media devices. I can then browse each one. When browsing a device I find out how many items there are and only request the first 100, once these have been received I trigger another request for the next 100 and so on until all items have been browsed. No timer, just simple handshaking.
Of course I needn't browse all the items as only the ones being displayed to the user are actually required.

Also I've seen many times, here in the Forum, people struggling with large databases. Often the problem is that a query is set to return many thousands of results, but only a very small subset of these are actually required. At any moment in time the end user can only view so much data when displayed on a small screen. Its often about rationalising what is required.

Maybe your requirement is similar? Could you get some of the required data, apply some calculations and then grab more data? Spliting the programming into manageable chunks rather than one big loop! You may even find that the code can be reduced as new functions are created and reused?

Ramblings over ;)
RandomCoder
 
Upvote 0

Troberg

Well-Known Member
Licensed User
Longtime User
I need all the data, and I need it more or less at once. It's a huge matrix, which I do some statistics on in various directions. Databases is something I'm good at, so I'm fairly sure that bit is reasonably efficient.
 
Upvote 0
Top