GUI callback interrupts timer callback causing deadlock

12 visualizaciones (últimos 30 días)
Linus Hein
Linus Hein el 18 de Ag. de 2022
Respondida: Bruno Luong el 22 de Ag. de 2022
Problem Context:
I am working on a project that has a GUI which is used to communicate with external hardware via a serial interface.
There are two types of communication with the external hardware in this project:
  • logging: (example: ask the hardware for its current status) done in regular intervals using timer
  • user-initiated: (example: make the hardware do something the user requests) done using a button callback function
It is essential that either type of communication does not get interrupted.
Problem:
  1. When a logging function (which was started by a timer) is running, the button callback function is able to interrupt the logging function's execution.
  2. In the button callback function, there is no way to pause execution of the button callback until the timer callback has finished its execution.
Things I have already tried:
  • a) waitfor in the button callback: causes the button callback to freeze up
  • b) pause in the button callback until the timer callback is done: does never goes back to the timer callback
Code example showcasing the issue:
classdef deadlock_gui < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
UIFigure matlab.ui.Figure
Button matlab.ui.control.Button
running
t
end
% Callbacks that handle component events
methods (Access = private)
% Button pushed function: Button
function ButtonPushed(app, event)
disp('Button has been clicked');
if app.running
disp('Timer function is currently running');
% waiting for the timer to stop running
% attempts to solve the problem
% a)
% waitfor(app, 'running', false);
% b
while app.running
pause(0.2);
end
end
if app.running
disp('Timer function is still running');
end
end
end
% Component initialization
methods (Access = private)
% Create UIFigure and components
function createComponents(app)
% Create UIFigure and hide until all components are created
app.UIFigure = uifigure('Visible', 'off');
app.UIFigure.Position = [100 100 411 268];
app.UIFigure.Name = 'MATLAB App';
% Create Button
app.Button = uibutton(app.UIFigure, 'push');
app.Button.ButtonPushedFcn = createCallbackFcn(app, @ButtonPushed, true);
app.Button.Position = [158 124 100 22];
% Show the figure after all components are created
app.UIFigure.Visible = 'on';
end
end
% App creation and deletion
methods (Access = public)
% Construct app
function app = deadlock_gui
% Create UIFigure and components
createComponents(app)
% Register the app with App Designer
registerApp(app, app.UIFigure)
if nargout == 0
clear app
end
app.running = false;
app.t = timer('TimerFcn', @(~, ~)app.timer_callback(), 'Period', 0.5, 'BusyMode','drop','ExecutionMode','fixedRate');
start(app.t);
end
function timer_callback(app)
app.running = true;
% communicate with external device that takes a long time
disp('start communicating with external device');
pause(4);
disp('stop communicating with external device');
app.running = false;
end
% Code that executes before app deletion
function delete(app)
% Delete UIFigure when app is deleted
delete(app.UIFigure);
stop(app.t);
delete(app.t)
end
end
end
To reproduce the error:
  1. save the above code in a file called "deadlock_gui.m"
  2. in the command window, run: "gui = deadlock_gui()"
  3. hit the button in the GUI that pops up
  4. To stop: hit CTRL-C, then run: "delete(gui)"
Callback trace will look something like this:
>> gui = deadlock_gui()
start communicating with external device
stop communicating with external device
start communicating with external device
Button has been clicked
Timer function is currently running
  1 comentario
chrisw23
chrisw23 el 22 de Ag. de 2022
Editada: chrisw23 el 22 de Ag. de 2022
Since you drop your timer event (per setup) in case of still busy state, you could also stop the timer before you start the interactive (button) communication. Be sure the serial port is ready to receive your request, because this has to be handled seperately.
I think the simulated 'pause(4)' isn't really what's happening during your serial communication, which should be a series of send and receive, giving Matlab the chance to update other code parts. The pause cmd will block all.
I would also use appdesigner instead of writing the code as a m File, which gives you the full editor support. If it's about code difference review use Matlab's VisualDiff tool for mlapp files.

Iniciar sesión para comentar.

Respuestas (1)

Bruno Luong
Bruno Luong el 22 de Ag. de 2022
Checkout parfeval that can be used run both tasks in parallel (I would put the log in background)

Categorías

Más información sobre Develop uifigure-Based Apps en Help Center y File Exchange.

Productos


Versión

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by