Tasker continues execution after "Perform Task" even though that task hasn't finished - bug?

2,670 views
Skip to first unread message

Achaiah A

unread,
May 13, 2013, 3:44:04 AM5/13/13
to tas...@googlegroups.com
Hmm, ran into a little bug/feature?? of tasker that's making life somewhat difficult. Just wanted to double-check my results with anyone else who may have seen it.

So I have a fairly complicated set of tasks part of which goes something like this:

1. Show Scene A
2. If Var Y (obtained from user interacting with scene A)
3. Run Task K (<- This task has Scene B in it that asks user for additional input)
4. Based on user input from scene in 'Task K' do Task L or M
5. Else Run Task O (<- This task has another scene in it that interacts with user)
6. Based on user input from scene in Task 'O' do some more tasks

As far as I understand, Tasker is single-threaded and is supposed to execute all tasks in order. Execution of the logic above starts off normally.  Scene A shows up without a hitch and all following tasks are waiting on the interaction in Scene A to complete.

Then, based on input Y either step 3. or 5. runs.  Here's where the problem (for me) creeps in.  It seems that due to the fact that my Scene B is not directly embedded into the execution of tasks but is rather called from within Task K (via "Perform Task"), Scene B executes in parallel with the main program.  So..Scene B will pop up but before I can even interact with it, the rest of tasks in the 'if' branch will execute without pause.  Unfortunately that plays havoc on the program since I count on the user to input things in Scene B before the rest of the 'if' branch executes.

Yes, I've tried pretty much every option to make Scene B not execute in parallel with the rest of the tasker calls but it seems to be impossible in this particular circumstance (i.e. executing a scene within another task using the "Perform Task" task). My only workaround is to create a separate global dummy variable and then use a wait-until to block on it until Scene B returns something sane.

Any thoughts / comments?

Thanks,


Achaiah

Bob Hansen

unread,
May 13, 2013, 4:32:13 AM5/13/13
to tas...@googlegroups.com
Not a bug, it's a feature.

To handle cases like yours, you can use the Tasks Running variable.
Tasks Running (dynamic) 
%TRUN
A comma-separated list of any named tasks which are currently running. The list always starts and ends with a comma to make matching easier, if it's not empty.

With this you can check to see if your task is still running and wait until it completes.

UncleMike

unread,
May 13, 2013, 3:23:25 PM5/13/13
to tas...@googlegroups.com
This issue is likely related to task priority.  If you have two tasks, A and B, and A launches B using Perform Task, then:

  • A & B will run concurrently if their priorities are equal
  • A will complete before B begins if A has a higher priority than B
  • B will complete before A continues if B has a higher priority than A

Achaiah A

unread,
May 13, 2013, 8:53:00 PM5/13/13
to tas...@googlegroups.com
Hmm interesting...sooo how do I control the priority of tasks?  I mean, I see how to control the priority of the task from "Perform Task" but what about the current task that's calling it?

Achaiah A

unread,
May 13, 2013, 8:54:40 PM5/13/13
to tas...@googlegroups.com
Thanks for the tip... so what would be the best way to handle this scenario?  Set up a wait-until loop that runs until the task name is no longer in the list?  Seems a bit wasteful.

UncleMike

unread,
May 13, 2013, 9:10:42 PM5/13/13
to tas...@googlegroups.com
Changing the priority of a task launched by a profile activation (as opposed to using Perform Task) is done on the Properties page for the profile.

Bob Hansen

unread,
May 13, 2013, 11:44:31 PM5/13/13
to tas...@googlegroups.com
The following is from Tasker: Action A-Z
When a task is started from an existing task, the existing task continues unless the Stop parameter is set. If you set the Stop parameter then the existing task will not continue at all, even after the called task has completed.

To handle your case you could add an action Wait Until. You specify the time between checks say 200ms and you specify the check condition which would be
  
 *,<your task name>,*   !~  %TRUN   

While your  "Task K" is running the Wait Until action's test will find Task K in the %TRUN list. As soon as Task K ends, it will no longer be in the list and the Wait Until action will be exited, and the Task processing continues.

1. Show Scene A
2. If Var Y (obtained from user interacting with scene A)
3. Run Task K (<- This task has Scene B in it that asks user for additional input)
!.  Wait Until  *,Task K,*   !~  %TRUN     <==wait to get input from Task K
4. Based on user input from scene in 'Task K' do Task L or M
5. Else Run Task O (<- This task has another scene in it that interacts with user)
!.  Wait Until  *,Task O,*   !~  %TRUN     <==wait to get input from Task O
6. Based on user input from scene in Task 'O' do some more tasks

Hope this helps...

Achaiah A

unread,
May 14, 2013, 3:59:08 AM5/14/13
to tas...@googlegroups.com
Dang... and this was done by design this way?  A bit frustrating to have to pattern match on a (potentially long) string list every 200-500ms.  I wonder if my previous solution of spinning and checking on a global int is more efficient for complicated tasks.  Sigh.  Many thanks for clarification though.

Bob Hansen

unread,
May 14, 2013, 4:19:02 AM5/14/13
to tas...@googlegroups.com
I don't think you understand. The wait isn't slowing anything down. It is forcing the main task to wait for the user input of the associated scene/task which must happen before the next action can be executed. The Wait actions is simply allowing a periodic check to see if the associated task has finished. The associated task is waiting for user input.

Rich D

unread,
May 14, 2013, 11:35:25 AM5/14/13
to tas...@googlegroups.com

> Dang... and this was done by design this way?  A bit frustrating to have to pattern match on a (potentially long) string list every 200-500ms.  I wonder if my previous solution of spinning and checking on a global int is more efficient for complicated tasks.  Sigh.  Many thanks for clarification though.

Bobs solution should work and might just be the easiest way however what you are trying to do should be able to be accomplished with the proper priority's being set. For something like this you will need a complete understanding of how the priorities work.. It mostly in the user guide but a little spread out. So if you search the guide for priority you should find most of it.  If you search the group you will find many posts on this.

  Here is just a example off the top of my head of how some of them work.  ** this should be verified with the user guide**

A task will always have a priority set by whatever starts the task and there are several ways to start a task....

1. With a profile.. the default for this is 5 and can be set In profile properties. This of course has exceptions when the 'enforce task order' is selected..

2. By a task cut or widget,,, there is a setting in tasker properties for these. I think they default at 6 or 7

3. By a perform task.... this is set in the perform task action

4.  By a element in a scene.  This I believe is set 1 higher than the task that showed the scene.

5. By the run button in task edit screen...  This one is what gets most in trouble.   A task started with the run button will always have a priority of 10. So when priorities are involved it is always best to start the task with whatever will be starting it in the actual project.  

*** AGAIN... this was just from memory and should be verified**

It is early mentioned as a rough guide to show the complexity of using priorities.   I am not even sure I mentioned them all.......

Hope this helps...

Rich..

Achaiah A

unread,
May 14, 2013, 12:54:07 PM5/14/13
to tas...@googlegroups.com
Right...but the wait is inefficient is all I'm saying. If every 500ms you have to do string pattern matching then this is expensive.  I'm assuming that under the hood everything is running in Java and using the Java patterns which are pretty cost prohibitive to compile over and over again ... unless somehow the pattern is already precompiled (which is the correct way to do it in Java).  Besides, it is an order of magnitude faster to run comparisons on integers than running pattern matching on strings (since you have to convert strings to numbers anyway for the CPU to process them).  I'm not saying it's a deal breaker but just pointing out that there are a lot more efficient ways (in Java anyway) to handle "waits".

Achaiah A

unread,
May 14, 2013, 1:01:57 PM5/14/13
to tas...@googlegroups.com
Rich,

Yeah I was looking at priorities but it's not really an elegant mechanism for what I want and is very fragile.  I'm basically building up a library of tasks in tasker that are 'helper' functions for other, more complicated, tasks.  For example, I have a basic task to save all current volume settings.  Then I have another one to restore them to the previously saved values.  These I call basic tasks.  I use them in many other tasks... e.g. when I want to interact with my phone by speech but the phone is on silent, I run the first task (save volume settings) then I change the volume of everything to the way that would make speech work well and then after I'm done I run my other task to restore the original values (because I still want my phone to remain on silent after I'm done with speech).

Priorities would work OK if I only had this one setup... but imagine that I have many different setups where I'm using my basic tasks to accomplish similar effects.  Now I have to worry about all the different ways that priorities might be set up for all of my basic  tasks so that they might run in the correct order.  It's a huge headache!  That's why it's a bit surprising to me that there isn't a more natural mechanism to control the execution flow.

Rich D

unread,
May 14, 2013, 2:15:39 PM5/14/13
to tas...@googlegroups.com

> Priorities would work OK if I only had this one setup... but imagine that I have many different setups

I agree with all you said. When I first started with tasker I was having a very difficult time getting things to go in the order I wanted them to. However I had no prior programing or development experience at all so I just wrote it off to my inexperience and hammered out my own solutions which in general meant making larger tasks with more sub tasks within the large task. I realize this is not a option for what you are trying to do just telling my story.  There are many talented programmers on here and hopefully they can help more than I can.

Rich...

TomL

unread,
May 14, 2013, 5:24:21 PM5/14/13
to tas...@googlegroups.com
I write and reuse tasks in the form of helper functions that I call with the action PerformTask all the time, and I don't run into any problems with priorities.  I don't usually have to bother tweaking the PerformTask priority levels beyond just remembering to either set it higher than the default priority, or lower than the default priority.

Besides, if I have a task where it's absolutely crucial that the steps listed after a PerformTask step runs after the PerformTask step completes, I'll split those steps off into their own profile, and have that profile detect exactly when to run properly.  

Decouple the Sequence Dependency, Improve the Flow of the Code.

Tom

Achaiah A

unread,
May 14, 2013, 9:37:03 PM5/14/13
to tas...@googlegroups.com
Tom,

I'm not really sure what you mean when you say "decouple the sequence dependency"?  All I'm trying to do is adhere to very basic code reuse principles: If I have a set of tasks that need to be executed over and over again from many different contexts, I wrap that set into a Tasker task....it's like wrapping up regular programming calls into a function/method so you can reuse that function elsewhere.  IMO this is a fairly natural and normal process and should require no extra effort.  I agree that with simple calls to Perform Task, one may get away with priority tweaking...but now imagine that you're trying to call "Perform Task" on a set of tasks that itself includes a few "Perform Task" tasks.  Now priority tweaking gets more complicated...

Matt R

unread,
May 14, 2013, 9:58:36 PM5/14/13
to tas...@googlegroups.com
One minor change if you want to stick with the "wait until" method: you could use the return action in the child task and have the parent task wait until the return variable is populated. This way you don't have to create a bunch of global variables.

Matt

Bob Hansen

unread,
May 14, 2013, 11:31:58 PM5/14/13
to tas...@googlegroups.com
I agree with Matt, the Return action would be a better method to handle the task waiting. I have never used that action so I didn't know about. Now I do. So mission accomplished I learned something today :>)

Achaiah A

unread,
May 15, 2013, 3:17:31 AM5/15/13
to tas...@googlegroups.com
That's great.  I think that this solution would work best... though I'm having a hard time following your instructions...could you clarify?

1. In the child task I create a "Return" with value 1.
2. In the parent task I create a "Perform Task"  with "Return Value Variable" set to %waitvar
3. Immediately after I have a "Wait Until" %waitvar is SET
4. Flash %waitvar     <-- does not seem to execute

Where am I going wrong?

Thanks!

Bob Hansen

unread,
May 15, 2013, 3:45:15 AM5/15/13
to tas...@googlegroups.com
I'm not sure what's happening here.

If you put a Flash %waitvar immediately before the wait until -- what and when does it flash?

It just occurred to me that the reason that we put the wait until there in the first place was because the child task was returning before the task was completed. So it appears to me that Return won't work for this case after all.

Achaiah A

unread,
May 15, 2013, 4:04:24 AM5/15/13
to tas...@googlegroups.com
Hmm I just got it to return after (what seemed to be inordinately) long time.  I think it will work, as long as it doesn't hang like that.  The original problem wasn't with the child process actually, it was with the parent continuing execution (of the if/else statement) while the child hasn't populated the global variable (upon which the "if" statement depends) with anything useful.

There is indeed a separate case where the child has a "Perform Task" within it that would cause the problem that you've mentioned, but if ALL "Perform Task" calls are handled the same way (with the return statement) then everything should execute in order.

Bob Hansen

unread,
May 15, 2013, 4:36:09 AM5/15/13
to tas...@googlegroups.com
After making the change, did you exit Tasker and then open it again?
There are times when edits don't take affect until Tasker is exited. 
I always seem to forget about that. That might explain why it finally started working.

TomL

unread,
May 15, 2013, 5:09:36 PM5/15/13
to tas...@googlegroups.com
I agree with your code reuse principles; that's how I roll too.

But the reality is that Tasker is more of a scripting tool than a full fledged language.  And deeply nested functions isn't its strong point.

My suggestion is that if you have a situation like this:

Profile A, context when something, do:
Task A (param1):
var local1 = perform Task B(param1) # this must run first ...
var local2 = perform Task C(local1) # .. then this... 
var local3 = perform Task D(local2) # ... after finally this
flash local3


... an alternative could be to restructure it like this:

Profile A, context when something, do:
Task A (param1):
var Global1 = perform Task B(param1)
stop

Profile B, context when Global1 is set, do:
var Global2 = perform Task C(Global1)
stop

Profile C, context when Global2 is set, do:
var local3 = perform Task D(Global2)
flash local3
stop


Tom

Achaiah A

unread,
May 16, 2013, 2:01:38 AM5/16/13
to tas...@googlegroups.com
Yeah, I get what you're saying Tom... but I'd rather not involve lots of global variables as it seems to slow down the system (from what I understand). I think Matt's suggestion will be OK, although it requires an extra step with the return variable.  Seems most sensible given the limitations of Tasker.  I wonder if I switch to javascript for some of these things if it will create a better flow.

TomL

unread,
May 16, 2013, 2:19:06 AM5/16/13
to tas...@googlegroups.com
Or call out to a shell script. That opens the door to shell commands, awk, sed, sqlite3, etc etc.

Tom

Achaiah A

unread,
May 16, 2013, 3:54:53 AM5/16/13
to tas...@googlegroups.com
Yeah, but the nice thing about javascript is that it can be used to execute tasker tasks  :)  I know there's SL4A too which has similar hooks into tasker.
Reply all
Reply to author
Forward
0 new messages