In App Designed app: When does a function called within another function spawn a new thread?
12 Comments
Hi @Gavin,
You mentioned, “I'm having SO much trouble! I think maybe when I call a function from within another function or callback it's going into a new thread. I want it to finish the function before moving on. Is the best way to do that to make the function return a (dummy) value?Since there is nothing to return but completion do I need to declare”
Please see my response to your comments below.
In MATLAB, when you call a function from within another function or a callback, it does not automatically create a new thread; however, the execution order can sometimes be confusing, especially with asynchronous callbacks. To ensure that the calling function waits for the called function to complete, you do not need to return a dummy value. You can simply define your function as follows:
function MyFunction(app) % Your code here end
If you do not need to return any value, you can call it without assigning it to a variable:
MyFunction(app);
Now, if you want to suppress warnings about unused return values, you can use the %#ok comment as you suggested:
fin = MyFunction(app); %#ok
However, it is not necessary to declare a return variable if you do not intend to use it. Just make sure that your function completes its execution before moving on to the next line of code in the calling function.
Hope this helps.
Hi @Gavin,
To address your concerns about managing function execution order in MATLAB App Designer, it is essential to understand the nature of asynchronous programming and how MATLAB handles callbacks. You probably aware of when a callback (like PicoInput%) is triggered, it executes asynchronously. This means that if another event occurs while the first callback is still running, the second callback may begin execution, leading to overlapping processes. So, to prevent this overlap, it is crucial to implement a mechanism that make sure one callback completes before another starts.
Now to address your query regarding, “Using waitfor function which is typically used to halt execution until a specified condition is met. However, it seems that you encountered issues using waitfor with RunTrial, which does not return an output value. A better approach would be to use a flag or a state variable to indicate whether the function is currently executing. For instance:
properties
IsRunning = false; % State variable
end function RunTrial(app, trlNum)
if app.IsRunning
return; % Exit if already running
end
app.IsRunning = true; % Set running state
% ... execute trial logic ...
app.IsRunning = false; % Reset state when done
endAlso, setting the Interruptible property of UI components can help manage how callbacks interact. If you want to make sure that certain critical functions (like reading from USB) are not interrupted, make sure they have Interruptible set to off. However, be aware that this will mean other user interactions won't interrupt these critical processes. For non-critical callbacks that might be interrupted, consider using the BusyAction property set to queue, this will make sure that if you trigger another callback while one is executing, the new callback will wait until the current one finishes rather than canceling it.
I saw that you are using dbstack, that cal really help you trace where errors occur in your code. If you encounter an error like "Not enough input arguments", checking the call stack at that point can provide insights into what might be going wrong.
It is frustrating that Asynchronous programming can often lead to complex scenarios in GUI applications where user interactions are frequent. That is why implementing state management techniques (like flags) greatly simplify control flow. Also, I would recommend testing various configurations of the Interruptible and BusyAction properties through trial and error which may help you yield insights into their effects on application responsiveness.
Hope this helps.
Hi @Gavin,
In addition to comments provided by @Walter Robertson and @Mario Malic, asynchronous programming allows multiple processes to run concurrently. In MATLAB, when a callback (like reading from a USB device) is triggered, it does not block the execution of subsequent callbacks. This can lead to complications if multiple events occur before the first one has completed. Implementing state management through flags or state variables is crucial. This allows you to prevent concurrent executions of critical functions. The provided code snippet below demonstrates this well:
classdef MyApp
properties
IsRunning = false; % State variable to track if the trial
is running
end
methods
function RunTrial(app, trlNum)
% Check if the trial is already running
if app.IsRunning
return; % Exit if already running
endapp.IsRunning = true; % Set running state
% Execute trial logic here
fprintf('Running trial number: %d\n', trlNum);
pause(2); % Simulate trial execution time app.IsRunning = false; % Reset state when done
end
end
endThis code checks whether a trial is already running before proceeding, thus preventing overlap.
Please see attached.

I would like @Mario Malic to provide his feedback based on the code snippet provided.
Accepted Answer
More Answers (1)
1 Comment
Hi @Gavin,
First, let me Thankyou for your compliment, @Umar was very helpful in understanding more about callbacks. After reviewing your recent posted comments, please see my response below.
Let me address your first query, “Is there a way to get info about all the running threads in a running app from the command window?”
Please refer to documentation provided below.
https://www.mathworks.com/matlabcentral/answers/2130561-display-active-threads-that-the-app-uses
Now addressing your query regarding, “One remaining question is about pause(1); if I start like this
function RunTrial(app,trlNum) % Don't run until Trial is complete while app.TrialRunning pause(1); AddDebugText(app,"Trial still running"); end % Continue with setting up the next trial
will the events (USB) keep being processed so the trial can actually finish? (Seems so)What about if I am running the debbugger in AD? It seems that too much gets halted when I hit a breakpoint or should it be just that thread. What if I re-enter the function that is paused? Will it hit the same breakpoint again (if the path through the routine with the break is hit) and pile up breaks? I think that is what was confusing me. I'd hit stop and it would just seem to sit at the same point until I stopped again.I'd need to set a breakpoint that is "out of the way" so the later passes can keep running if needed.”
Please see my detailed response to your second query.
Behavior of pause(1) in Your Code
After reviewing the pause function documentation provided at the link below
https://www.mathworks.com/help/matlab/ref/pause.html
So, analyzing your provided code snippets, when you will use pause(1); inside your RunTrial function, MATLAB will indeed halt execution of that particular thread for 1 second. However, it's important to note that while this thread is paused, other threads (including event handling threads) can continue to process events. This means that USB events or other asynchronous tasks should still be handled, allowing your trial to complete even if the main thread is temporarily inactive. For instance, if you have an event listener set up for USB input, it should still receive and process data during the pause period.
Debugging with Breakpoints
When debugging with breakpoints in MATLAB, only the thread where the breakpoint is hit will be halted. This means that if your application is multi-threaded, other threads can continue executing unless they are also stopped by hitting a breakpoint. However, if you re-enter the function that contains a breakpoint while it’s paused (for instance, if the function is called again due to an event), it will hit the same breakpoint again each time it reaches that point in code execution. This could indeed lead to what seems like "piling up" of breakpoints if you continuously trigger the function before resolving the initial breakpoint.
Setting Breakpoints Strategically
To avoid confusion with multiple breakpoints being hit, you may consider setting conditional breakpoints or placing breakpoints at points in your code where they won't be hit frequently during normal operation. For example, you could place breakpoints at the beginning of a new trial setup rather than within the loop that processes trials. Additionally, using dbstop if error can help catch errors without halting execution unnecessarily on every iteration.
I would advise when you debug complex applications, wrap code sections in try-catch blocks because it can help manage unexpected errors without completely halting execution flow.
Please let me know if you have any further questions for us.
Categories
Find more on Scripts in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!