Executing two callbacks concurrently

12 views (last 30 days)
Kris
Kris on 28 Mar 2012
Hello,
In a single figure, I've positioned two axes each controlled by a 'plot now button' (see code below). When either of the two buttons are pressed an image is slowly displayed line-by-line in the respective axis. If say button 1 is pressed and then while the image is being displayed in the first axis, then button 2 is pressed, the image in axis 1 pauses to give control to the second axis - which then displays the image. When image two is fully drawn then image one continues off where it left off.
What I would like to happen is for image one to continue displaying the image even when button 2 is pressed so that both images concurrently are being drawn. Options such as 'Interruptible' or 'BusyAction' in the callback aren't really of help to me because I would like both axes to fill simultaneously (i.e., when the button is pressed, draw the image irrespective of whatever else is going on).
As I understand it now, GUI callbacks share the same single queue and that when a callback initiates you cannot know whether another callback is executing.
I was hoping there was a way to do this with the parallel toolbox but as I understand it workers don’t have access to graphics objects (I've tried accessing figure handles from a single worker and I'm unable to).
The only way to concurrently draw images that sort of works is for me to start up two separate matlab clients and have each one control a single plot (but that 'solution' is really ugly).
Can anyone suggest something I haven't thought of to solve my dilemna of getting essentially two callbacks to execute concurrently?
(If you run the sample code push 'button 1' and then press 'button 2' before the image finishes displaying and you'll see what I'm getting at.
Cheers, Kris.
function SimultaneousPlot
%Concurrent execution of two callback functions
close all; clc;
f1 = figure(1);
ax1 = subplot(1,2,1);
ax2 = subplot(1,2,2);
uicontrol( 'Parent', f1, 'String', 'Button1', 'Position', [150 1 50 25]', ...
'Callback', {@funtest1 ax1})
uicontrol( 'Parent', f1, 'String', 'Button2', 'Position', [400 1 50 25]', ...
'Callback', {@funtest2 ax2})
function funtest1(hObj, event, ax)
disp('Button1')
x = randn(31);
y = zeros(size(x));
for i = 1:31,
y(1:i,:) = x(1:i,:);
imagesc( y, 'Parent', ax);
drawnow
pause(0.2)
end
function funtest2(hObj, event, ax)
disp('Button2')
x = membrane( 1, 15 );
y = zeros(size(x));
for i = 1:31,
y(1:i,:) = x(1:i,:);
imagesc( y, 'Parent', ax);
drawnow
pause(0.2)
end

Answers (3)

John
John on 28 Mar 2012
I don't particularly care for this solution but it is one quick way to get at what you're trying to do (I think), hope it helps!:
function newTest
f1 = figure(1);
ax1 = subplot(1,2,1);
ax2 = subplot(1,2,2);
plot1 = false;
plot2 = false;
plotStarted = false;
Idx1 = 1;
Idx2 = 1;
uicontrol( 'Parent', f1, 'String', 'Button1', 'Position', [150 1 50 25]', ...
'Callback', {@startPlotting})
uicontrol( 'Parent', f1, 'String', 'Button2', 'Position', [400 1 50 25]', ...
'Callback', {@startPlotting})
function startPlotting(hObj, event)
% Set the plotting toggles
if strcmp(get(hObj,'String'),'Button1')
plot1 = true;
else
plot2 = true;
end
% Starting plotting
if ~plotStarted
funtest3();
end
plotStarted = true;
end
function funtest3(hObj, event)
% Set the data to be plotted
x1 = rand(31);
y1 = zeros(size(x1));
x2 = membrane( 1, 15 );
y2 = zeros(size(x2));
% Loop over both data sets and update the plots if each's
% respective toggle is set to true
while (plot1 && Idx1 <= 31) || (plot2 && Idx2 <= 31)
if plot1 && (Idx1 <= 31)
y1(1:Idx1,:) = x1(1:Idx1,:);
imagesc( y1, 'Parent', ax1);
Idx1 = Idx1 + 1;
end
if plot2 && (Idx2 <= 31)
y2(1:Idx2,:) = x2(1:Idx2,:);
imagesc( y2, 'Parent', ax2);
Idx2 = Idx2 + 1;
end
drawnow
pause(0.2)
end
end
end
  1 Comment
Daniel Shub
Daniel Shub on 28 Mar 2012
I agree that this implementation is not ideal since it doesn't scale well, but I could imagine a similar approach that would scale well.

Sign in to comment.


Geoff
Geoff on 28 Mar 2012
Okay, assuming for a start that you can concurrently update a figure from two threads, you could try timers.
The theory here is similar to creating a worker-thread in normal GUI applications. As in MatLab, GUI applications usually have a message pump that sends messages or fires callbacks from a single thread. The way you deal with these is to create or wake up another thread to do the work, and return control immediately to the message pump.
So, what you could try is to create a single-shot timer whenever a button is pressed, which 'immediately' fires your draw function and then self-destructs.
I don't know enough about MatLab's internal handling of timers to say if this will work (eg, if timers are all handled from a single thread) but it's worth playing around. It won't take much at all to setup the timer. Check the documentation for timer if you are not familiar with them.
If MatLab has implemented their own version of timers without relying on existing operating system APIs, then there's a real possibility that each timer is a self-contained thread. If so, those threads just might be able to make MatLab calls simultaneously.
  1 Comment
Daniel Shub
Daniel Shub on 28 Mar 2012
I am pretty sure your approach with a single shot timer will not work. MATLAB is essentially single threaded, so timers are all handled from a single thread which is in fact the same thread that handles the main computation and gui callbacks. There is a slight caveat that timers are initiated from a separate thread and therefore there code be be injected into the main thread. But MATLAB will only do 1 thing at a time.

Sign in to comment.


Daniel Shub
Daniel Shub on 28 Mar 2012
This is a perfect situation for a timer. You can set the TasksToExecute property of the timer to 31 (the number of times you loop), the period to be 0.2 (the duration of your pause), and the callback to do:
y(1:i,:) = x(1:i,:);
imagesc( y, 'Parent', ax);
drawnow;
Then your gui callback would simply start the timer object. You will have to play around with passing the right information (x and ax) to the timer when you create it.

Categories

Find more on Graphics Performance 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!