Concurrent Methods

I have multiple methods each one controls a different area in the app. I want to run all of them concurrently when a button is pressed.

Is this possible?

No. At best you can do is use a Thread or Workers. Read up on threads and workers to find the limitations of each. Xojo doesn’t /really/ have a concurrency option.

2 Likes

But that’s not really concurrency; it’s cooperation. With concurrent threads, everybody runs at the same time using different cpu cores and everything gets done quicker. Cooperative threads yield no speed advantages; they actually make everything slower. Xojo threads do have some advantages, but I don’t think that’s what the OP was asking.

2 Likes

Can you tell us more about what these methods do? It will help us best advise you on which approach to use.

Essentially the method calls a thread but the threads get a parameter to run the same thread off of different fields.

I want the thread essentially to run concurrent with other threads. I have tried running both threads and methods concurrently and neither is getting what I want.

But what are the threads actually doing? Are they processing image data, for example, or doing mathematical calculations? Understanding this is key to creating an effective strategy.

The threads run a SQL Query and Process the data into a new format outputting to a text file on the desktop.

How much time do you expect the process to take?

It varies based on the query and the thread.

There are 5 sections in the app. Each identical and all on one container screen. On each of those sections is a combobox with 5 options. The options in the combo box are the same for each section. Each section can be ran independently OR ideally, all sections with valid fields filled out can run concurrently.

There is a thread for each of the 5 options. Each option will output the SQL queried data in a different manner. Each section can run different or the same options. So I am passing a parameter to the thread to tell it which section is running it, and within the thread it checks that parameter and uses the appropriate fields for the section that it was passed. A field might be the output file name, so I can run the same option in two different sections but modify the sql query (which would be a different field) between them and write to the respective filename. Allowing me to take a large chunk of data and split it up via the query code.

So long answer short, every time I run one of the queries for an option the time to completion varies.

Ok. That’s really helpful, thanks.

If your queries/data analysis is taking more than a few seconds, you would probably benefit from breaking the SQL query and data analysis into a Worker (or a Console app) and run one of those for each section of the app. These processes would be truly independent from your main app, with their own memory space and CPU allocation and will run concurrently. Once they have retrieved their data and have prepared it, they can save it to a file and report back their status to the main app, which reads in the data and displays it. Essentially, if you have five sections that each takes 5 seconds to populate, your current app will need about 25-30 seconds to finish. A concurrent solution could be done in 5-8 seconds; i.e., approximately the time a single section would take.

This does have the consequence that each process will need its own connection to the database server - it can’t be shared between them.

Breaking your app into little pieces like this can seem like a lot of work but it is the best way to take advantage of all those unused CPU cycles that a single Xojo app cannot utilize. I’ve used this approach for image analysis and, properly engineered and in the right scenario, it can dramatically improve performance.

Xojo uses one real thread for all. This is specially worrisome in some I/O operations because any kind of hold stops all your “Xojo Threads”.

What Xojo calls threads are technically “Fibers”, cooperative time-slicing, and works like this:

In the above graphic, what I called “task” is a Xojo Thread.

This may be enough for many scenarios, and improper for others. Analyze you use case.

Have you considered using shared memory? This would avoid disk access and improve performance. You can create and access shared memory (on the Mac at least) with declares.

When I read your overview, I see two major slowdowns.

  1. Disk access to the SQLDatabase. AFAIK this is going to be sequential, it won’t be able to perform more than one query at once.

  2. Updating the UI. This is one of the slowest points as UI updates can only be performed one at a time. If you’re using the Xojo Listbox, you’ll want to “hide” it before adding rows and then “show” it once you’re done. IIRC Xojo asks for a redraw everytime you add a row. Xojo’s listbox is also NOT lazy loading, so you must add all the rows in one go. Lazy loading is popular in other dev tools, as the list control only creates and displays views when the customer scrolls them into view. So you can display 10s of 1000s of records in the blink of an eye, but actually the list control is only displaying as many as the customer can see. IIRC pidog has a lazy loading listview.