A better solution would be to use separate threads (one for the user interface and one for processing), possibly using a parallel toolbar. In any case, it would be rather difficult to synchronize both.
So, here is a simple solution that relies only on anonymous functions (to delegate an interface that is refreshing outside the processing unit) and on a drawnow function (to make the GUI process its messages).
Application example
The sample application for working with it is very simple. He contains:
- Settings panel (with only one setting, the number of iterations for the processing unit)
- Progress bar
- Go / Cancel Button
NB: The source code is quite long (about 250 lines, mainly due to the creation of gui), so I omitted it here .

Creating a GUI is not important. The most important parts are the processing unit, anonymous functions that allow code and callbacks to respond to GUI events. Thus, I will describe theses in detail.
Processing unit
The processing block is a simple procedure:
function [] = processing(count, instrumentation) %[ for ki = 1:count, instrumentation.CheckCancel(); instrumentation.Progress((ki-1)/count); if (ki > 1), pause(1); end instrumentation.CheckCancel(); instrumentation.Progress(ki/count); end %] end
The only feature in this is that it requires an additional instrumentation structure. This structure has two fields that point to two anonymous functions defined by the caller (i.e. a graphical interface). We will soon see how.
CheckCancel is the function responsible for raising the error if the user wants to stop processing.Progress is a feature that can be used to delegate a progress report.
This is how anonymous functions are connected to the graphical interface (see the doProcessing subfunction in the code):
% Connect instrumentation callbacks with the gui instrumentation.CheckCancel = @(ratio)onCheckCancel(dlg); instrumentation.Progress = @(ratio)onProgress(dlg, ratio); % Perform the processing processing(settings.NumberOfIterations, instrumentation);
Handlers of progress and verification.
Here is the graphical interface handler for Progress :
function [] = onProgress(dlg, ratio) %[ % Update the progress bar value data = guidata(dlg); uiprogress(data.handles.pbProgress, ratio); % Force interface to refresh drawnow(); %] end
It's simple, it just updates the progressbar control and forces the GUI to be updated (recall that Matlab is single-threaded and is currently executing a processing unit, so we need to force the GUI to be updated).
Here is the handler for CheckCancel :
function [] = onCheckCancel(dlg) %[ % Force interface to process its events drawnow(); % Check 'UserData' has not been modified during events processing guiState = get(dlg, 'UserData'); if (~isempty(guiState) && .... strcmp(guiState, 'CancelRequested') || strcmp(guiState, 'CloseRequested')) error('System:OperationCanceledException', 'Operation canceled'); end %] end
Again, this is pretty simple. We force the GUI to handle events (button clicks, etc.), and then we read if UserData been changed to some expected value. If so, we throw an exception to stop processing. Remind again that the current executable code is a processing unit.
GUI Event Handlers
There are only two interesting events in the graphical interface. Either the user clicks the close button, or he clicks the "Go / Cancel" button.
Note. We remind you that even if Matlab is blocked during the execution of the processing unit, GUI events are still processed, since the processing unit occasionally causes drawnow (based on the average value of the toolkit delegates).
Here is the close button code:
function [] = onCloseRequest(dlg) %[ % If already in computation mode if (~isempty(get(dlg, 'UserData'))) % Just indicate close is requested and leave immediatly set(dlg, 'UserData', 'CloseRequested'); data = guidata(dlg); set(data.handles.btnGoCancel, 'Enable', 'off', 'String', 'Cancelling...'); return; end % Immediate close delete(dlg); %] end
It is simple, if we are in the operating mode, we simply signal that we want to stop, otherwise we will immediately close the dialog box.
Here is the go / cancel button code:
function [] = onGoCancelClick(dlg) %[ % If already in computation mode if (~isempty(get(dlg, 'UserData'))) % Just indicate cancel is requested and leave immediatly set(dlg, 'UserData', 'CancelRequested'); data = guidata(dlg); set(data.handles.btnGoCancel, 'Enable', 'off', 'String', 'Cancelling...'); return; end % Go into computation mode [settings, err] = tryReadSettings(dlg); if (~isempty(err)) waitfor(msgbox(err.message, 'Invalid settings', 'Error', 'Modal')); else enterComputationMode(dlg); err = doProcessing(dlg, settings); leaveComputationMode(dlg, err); end %] end
This is a little longer, at least it is one and the same. If we are in operating mode, we simply indicate that we want to stop; otherwise, the interface is in normal mode, and we begin processing.
The functions tryReadSettings , enterComputationMode and leaveComputationMode are just adhesives for updating controls in the interface and for a pleasant report of errors or cancellations.
Conclusion
We have developed a flexible graphical interface that relies only on drawnow and anonymous . This, of course, is just a trick, and the best solution would be to use multitasking.
The graphical interface was created here programmatically. The principle is the same if you build with GUIDE or using the GUI Toolbar .
Tool callbacks can be further improved, for example by adding a Log field to report processing data to a text field or to some end similar to Log4Net (only with message level and message value). Or by adding a callback for intermediate results.
The interface can also be improved or changed, for example, why not start processing whenever the parameter has been changed (that is, just stop any current start and without having to manually press the "Go / Cancel" button each time).
There are many possibilities. Here, just providing some ground-based applications to get you started (or not ...).