Unlimited background tasks

My Win/Mac/Linux project has button that fires a task* which could take a few seconds to finish but I need to prevent the program of freezing.
Actually I would like the program to keep accepting this same button click events and thus duplicate and fire as many tasks as necessary.

Is it a good practice to write a Thread (task) and ask the click event to duplicate it ?

[quote]* Task example:
1st: Store current timedate in var : startTimedate
2nd: Sleep random seconds (for test purposes)
3rd: Listbox1.AddRow ("Started at " + startTimedate + " and finished at " + current system time)[/quote]

[quote=116849:@Walter Sander]1st: Store current timedate in var : startTimedate
2nd: Sleep random seconds (for test purposes)[/quote]

1 probably takes a couple microseconds, I frankly don’t see any need for a thread. As for 2, why on earth impose a delay in a thread ? ? ?

You cannot access the UI from a thread, so that will not be possible.

I will suppose that your program does long calculus or something that justify a thread.

Now, you could indeed start a new thread each time the user clicks, but it can be messy if you want to coordinate the results.

Why not instead create a queue into which each click adds a task to be added to the thread ?

I would like to run multiple tasks in parallel to achieve results faster and thus my application will be much more responsive.

That, I understand. Careful what you wish for :wink:

Here is how you create a thread dynamically :

dim tata as new Thread AddHandler tata.run, AddressOf robert tata.run

Sub robert(sender as Thread) system.DebugLog "Robert" End Sub

You can create as many threads as you want.

Please note that still, you need to use methods created in the IDE to manage the threads code. So in effect, the number of threads is limited by the number of delegates. Or you can reuse methods.

Have fun !

More threads = more overhead = slower results, not faster. Running tasks in parallel does not make them faster. At least in a cooperative threading model like Xojo.

You could spawn subprocesses though, and take advantage of multiple cores.

[quote=116849:@Walter Sander]My Win/Mac/Linux project has button that fires a task* which could take a few seconds to finish but I need to prevent the program of freezing.
Actually I would like the program to keep accepting this same button click events and thus duplicate and fire as many tasks as necessary.[/quote]

I may not have been clear enough the first time around, but starting a new thread each time the button is clicked is probably not very bright. As Tim Hare pointed out, adding threads will only grab more and more processing power, slowing down the whole app.

The best course of action for such a problem is to use a queue where tasks are stored in a to-do list each time a click is done, and then run in the thread in the order they where added.

Even with such a provision, allowing the user an infinite number of clicks while tasks take several seconds to complete looks like a bad design. What will happen if the user decides to click ten times in a raw in less than a second ? Some sort of limits to the frequency of clicks and their numbers must be set, otherwise the app will be overloaded.

Thank you guys for your thoughts. Maybe I could mix both solutions:

In a later stage, I could even increase/decrease the X value to make use of available system resources.

Tim I know what you saying and it would make sense for blocking code job even though running in parallel tasks … that’s why I made the point: “prevent the program of freezing” or in other words, make non-blocking tasks :wink: But you’re right, these tasks will get slower and slower and at some point it would not compensate to run them in parallel

[quote=116984:@Walter Sander]Maybe I could mix both solutions:

Queue + cap of X parallel jobs.

In a later stage, I could even increase/decrease the X value to make use of available system resources.
[/quote]

The word “parallel” does not quite reflect what threads are. In effect, threads execute in the background but are not truly parallel, as they use the same processor core. The only way to achieve true parallel processing would be to spawn subprocesses. But this would be a lot more involved.

Back to the option to mix queues and several thread. Yes, of course, you can mix. The issue you will face is the need to coordinate tasks. Let us say a task is made of 3 steps : get parameters/calculate 3 seconds/hand the result to a timer to update the listbox.

In the one queue+one thread model, each time the user clicks, a task is put on the pile with the parameters. Here starts a problem : what are the parameters stored ? If your application uses for instance TextFields with numbers as base for the calculus, it probably would not make sense to launch the same task with the same parameters twice in a raw. So you should probably verify that parameters are not the same before piling a new task.

Then, imagine the (fast) user changes the data and clicks at the rate of 1 per second. With one thread, while the first task is still executing, the user will have queued 3 new ones. So if the task manager (most probably in a timer) waits for each task to complete before sending a new one, that accounts for a total of 4 tasks x 3 seconds = 12 seconds total.

In order to have a faster response time, it makes sense to use 4 identical threads, each managing a task, so the result may be ready in 3 seconds after the click.

This looks like what you wanted to do initially, but using a queue and a task manager will enable using a finite number of threads and allocate tasks to each according to availability. So if the crazy user keeps inputing new data, your program will not miss anything and keep being responsive.

Now, on the other end of the tunnel, you need to coordinate things as well. If you have only one thread, it is simple enough : a timer can check if the thread has ended, and if so, collect the result and update the listbox. But if you have several threads running from your temperamental user, then you need to monitor all of them. And place the result in good order in the listbox. If each task takes a fixed time to complete, that is fine. If that time is variable, you need to know the order in which tasks where input to update the listbox in the same order.

In fact, there are no theoretical obstacles to the number of threads, but in practice, the queue and a task manager is the only way to insure a smooth business. And also, your user interface must be conceived to update gracefully without major disruption to the user.