Undocumented Matlab
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT

Waiting for asynchronous events

July 18, 2012 33 Comments

It often happens that we need our program to wait for some condition to occur. This condition may depend on some external process that updates the condition asynchronously, meaning in a non-predictable (non-specific) time. A typical example is user mouse or keyboard actions in a GUI dialog window, or a specific signal that is received from hardware.

waitfor and other built-in functions

Matlab has a couple of built-in functions for blocking Matlab’s main processing thread until certain asynchronous GUI events occurs. waitfor is documented to block code execution until either the specified GUI handle object is deleted, or is updated (possibly to a specified value), or Ctrl-C is pressed in matlab’s Command Window. uiwait similarly blocks execution, until a specified figure handle is deleted/closed, or a separate processing thread (typically, a callback function) calls the corresponding uiresume (I discussed uiwait/uiresume, together with their uisuspend/uirestore siblings, last year). uiwait, unlike waitfor, has an optional timeout parameter; on the other hand, uiwait cannot wait for a non-deletion event on a regular uicontrol property, as waitfor can.
Other related built-in Matlab functions are waitforbuttonpress, pause (which awaits user mouse/keyboard clicks), and ginput, gtext, rbbox, dragrect (which awaits mouse clicks in a plot/image axes). Some toolboxes have other similar blocking functions, for example roipoly in the Image Processing toolbox.

Waiting for events on non-HG objects

But what if we need to wait for an event to happen on a non-Matlab (HG) object? Say on an ActiveX control property or even on a non-graphical Java object?
It turns out that waitfor can also be used in these cases. Although not documented, waitfor actually accepts handles not only of HG objects (e.g., figure handles) but also of other types of handles, such as regular Java reference handles. The usage is the same as for regular HG handles:

waitfor(objectHandleOrReference, 'propertyName', propertyValue);

waitfor(objectHandleOrReference, 'propertyName', propertyValue);

For example, to wait for data to be available in a java.util.Hashtable object, which has a public boolean isEmpty() method and therefore returns a value of ‘on’ or ‘off’ for get(object,’Empty’):

waitfor(javaHashTableReference, 'Empty', 'off');

waitfor(javaHashTableReference, 'Empty', 'off');


(Note that Matlab automatically converts a Java boolean into ‘on’/’off’ in such cases, so we need to use ‘on’/’off’ rather than true/false; this is not always the case – a counter-case is presented immediately below)

Setting a timeout on waitfor

To set a timeout on our blocked wait, a feature of uiwait that is missing in the built-in waitfor, we can use a dedicated one-time timer object. Timer callbacks use a separate thread from the main Matlab processing thread, and are therefore processed even when the Main thread is blocked. The implementation is quite easy, as shown below:

% Wait for data updates to complete (isDone = false if timeout, true if data ok)
function isDone = waitForDone(object,timeout)
    % Initialize: timeout flag = false
    object.setDone(false);
    % Create and start the separate timeout timer thread
    hTimer = timer('TimerFcn',@(h,e)object.setDone(true), 'StartDelay',timeout);
    start(hTimer);
    % Wait for the object property to change or for timeout, whichever comes first
    waitfor(object,'Done',true);
    % waitfor is over - either because of timeout or because the data changed
    % To determine which, check whether the timer callback was activated
    isDone = (hTimer.TasksExecuted == 0);
    % Delete the time object
    try stop(hTimer);   catch, end
    try delete(hTimer); catch, end
    % Return the flag indicating whether or not timeout was reached
end  % waitForDone

% Wait for data updates to complete (isDone = false if timeout, true if data ok) function isDone = waitForDone(object,timeout) % Initialize: timeout flag = false object.setDone(false); % Create and start the separate timeout timer thread hTimer = timer('TimerFcn',@(h,e)object.setDone(true), 'StartDelay',timeout); start(hTimer); % Wait for the object property to change or for timeout, whichever comes first waitfor(object,'Done',true); % waitfor is over - either because of timeout or because the data changed % To determine which, check whether the timer callback was activated isDone = (hTimer.TasksExecuted == 0); % Delete the time object try stop(hTimer); catch, end try delete(hTimer); catch, end % Return the flag indicating whether or not timeout was reached end % waitForDone

Polling

In some cases (for example, waiting on a specific field value within a struct, which waitfor does not support), we need to revert to using plain-ol’ polling, rather than the more efficient blocked wait. In such cases, I strongly advice to place a certain pause within the polling loop:

delay = 0.01;  % 10 milliseconds
while ~object.isDone  % set by the callback
    pause(delay);  % a slight pause to let all the data gather
end

delay = 0.01; % 10 milliseconds while ~object.isDone % set by the callback pause(delay); % a slight pause to let all the data gather end

Or, a variant with timeout:

delay = 0.01;
for idx = 1 : (timeout/delay)  % wait up to N secs before giving up
    if object.isDone  % set by the callback
        break;
    end
    pause(delay);  % a slight pause to let all the data gather
end

delay = 0.01; for idx = 1 : (timeout/delay) % wait up to N secs before giving up if object.isDone % set by the callback break; end pause(delay); % a slight pause to let all the data gather end

The reason we need this deliberate pause is to enable the CPU to process other processing threads, namely that thread which is responsible for updating the field value in due time. Without this pause, it would take the CPU much longer (if at all) to get to that thread, and our overall application performance will actually degrade, since the event will take longer to get processed.
Adding deliberate pause delays as a mechanism to improve overall performance may sound counter-intuitive, but this is in fact the case here. Performance tuning can indeed be counter-intuitive sometimes, until you learn the underlying reasons when it becomes clear (I’ve shown several examples of this in the past, here, here, here and here).
We should take care not to set too high a pause delay, since that will unnecessarily delay processing of the incoming event; on the other hand, setting it too low will return the thread-starvation issue explained above. A pause value of 5-50 millisecs (0.005-0.05) should be about right for the vast majority of applications. Note that different platforms run your application at different speeds, so be careful not to over-tune this delay to a particular computer.
Interested in learning more Matlab performance or advanced programming tricks? Then consider joining my Matlab Performance Tuning, Advanced Matlab GUI and/or Matlab-Java programming seminars in Geneva on August 21-23, 2012 – email me (altmany at gmail dot com) for details.

Related posts:

  1. Blocked wait with timeout for asynchronous events – It is easy to convert asynchronous (streaming) events into a blocked wait in Matlab. ...
  2. Matlab callbacks for Java events – Events raised in Java code can be caught and handled in Matlab callback functions - this article explains how...
  3. Matlab callbacks for Java events in R2014a – R2014a changed the way in which Java objects expose events as Matlab callbacks. ...
  4. UDD Events and Listeners – UDD event listeners can be used to listen to property value changes and other important events of Matlab objects...
  5. Undocumented HG2 graphics events – Matlab's new HG2 graphics engine includes many new undocumented events that could be used in various ways. ...
  6. Matlab callbacks for uifigure JavaScript events – Matlab callback code can be attached to JavaScript events in web-based uifigures. ...
ActiveX Callbacks Java Performance Undocumented feature
Print Print
« Previous
Next »
33 Responses
  1. Brad Stiritz July 21, 2012 at 08:24 Reply

    Hi Yair,

    Thanks for your post, very interesting.

    It seems like conceptually, one could create an effectively multi-threaded MATLAB application using the ideas in your posting & the MATLAB compiler. Each thread would be deployed as a separate process & messages / event info would be passed between the processes via a robust message broker, e.g Java GlassFish.

    I’m also thinking it might be possible to take this idea one step further, via the Parallel Computing Toolbox. Worker threads could be programmed to immediately go into async “stand-by”, per your post, & then be controlled via the message architecture. This would cut out the PCT set-up/retrieval overhead, which over hundreds of parallel jobs could be significant.

    Have you ever worked on or heard of any MATLAB projects where something like this has been done successfully? It seems pretty straightforward, doesn’t it? Do you have any experience using MATLAB & GlassFish together? If so, how did things go?

    Any comments appreciated,
    Thanks,
    Brad

    p.s. I wasn’t able to get the HTML carriage return tag “br” or the paragraph break tag “p” to work in my comment. Could you please advise on how to achieve paragraph breaks?

    • Yair Altman July 21, 2012 at 10:38 Reply

      @Brad – thanks. I haven’t used GlassFish before. What you suggested sounds reasonable on first read, but I have never attempted such inter-process Matlab communications. I do know that Matlab IPC has been attempted by others, though. There are even several such mechanisms on the File Exchange, although I don’t know whether they use an efficient async mechanism or inefficient polling.

      Re para break, simply press the ENTER key twice – this will automatically create the paragraph break that you were looking for, just as in you own comment.

  2. Alex July 26, 2012 at 02:56 Reply

    Is it possible to set a timeout for a calculation? I’m calling an external function that doesn’t always converge, so it is possible that MATLAB stays busy forever when I call the function. I want to do something like this:

    try(timeout = 60)
    external_fun;
    catch ME
    error('Function did not converge in 60 seconds')
    end

    try(timeout = 60) external_fun; catch ME error('Function did not converge in 60 seconds') end

    • Yair Altman July 26, 2012 at 02:59 Reply

      @Alex – no, but you could add a check for the timeout condition in your calculation function (in its main loop for example), if you can modify its source code.

  3. Brad Stiritz July 28, 2012 at 14:31 Reply

    Yair,

    Thanks for your reply. Looking at the MATLAB MCR documentation, it says:

    “The MCR makes use of thread locking so that only one thread is allowed to access the MCR at a time. As a result, calls into the MCR are threadsafe for MATLAB Compiler generated libraries, COM objects, and .NET objects. On the other hand, this can impact performance.”

    Do you think this also means that only one *process* is allowed to access the MCR at a time? If so, then wouldn’t this effectively preclude multiple deployed apps from running at the same time? That doesn’t seem right, though, does it?

    • Yair Altman July 29, 2012 at 02:08 Reply

      @Brad – I do not have any additional information on this. It should be simple enough to test, and you could always ask MathWorks support about this.

  4. Tomás Peyré August 27, 2012 at 01:08 Reply

    Yair,
    I’ve doing data polling from a sensor with Matlab’s pause command in the loop for some time.
    My application was leaking memory and would crash after several hours.
    Matlab support confirmed they have a memory leak issue when calling pause within a loop on R2011b and R2012a.

    Inspired in your use of Java native functions, I wrote this alternative pause function that solve the problem for me and may help others:

    function pauseJava(tPauseSec)
    	th = java.lang.Thread.currentThread();  %Get current Thread
    	th.sleep(1000*tPauseSec)                %Pause thread, conversion to milliseconds

    function pauseJava(tPauseSec) th = java.lang.Thread.currentThread(); %Get current Thread th.sleep(1000*tPauseSec) %Pause thread, conversion to milliseconds

    • Yair Altman August 27, 2012 at 02:25 Reply

      @Tomás – thanks for the information and the workaround 🙂

  5. Pause for the better | Undocumented Matlab August 29, 2012 at 11:02 Reply

    […] A few days ago, blog reader Tomás Peyré commented on the fact that the pause function has a memory leak on R2011b and R2012a […]

  6. Jim Hokanson August 29, 2012 at 14:00 Reply

    Hi Yair,

    Any ideas on how to accomplish what you describe above with Matlab objects? I tried passing in a handle class object and Matlab didn’t like it.

    Thanks,
    Jim

  7. Take a break, have a pause() | matlabideas May 18, 2013 at 08:34 Reply

    […] pause() has a memory leak […]

  8. Rafael May 30, 2013 at 09:58 Reply

    Yair, this web site is an incredible resource. Thank you!!

    A long time ago I created code that has loops like the one you show here to wait for asynchronous events. But it never works well. All of the testing I have done indicates that no other threads are executed when Matlab executes a pause command. The wait loop never receives the event, because the thread that is supposed to create the event never gets executed while the wait loop is running. Are you sure Matlab does allow other threads to run while a pause is executing?

    Thanks!

  9. Bolivar July 31, 2013 at 10:52 Reply

    do waitfor only take java object as arguments or matlab object reference as well? If so which package should i add to be able to implement the the waitForDone function described above?

    Thanks for your support!

    • Yair Altman July 31, 2013 at 11:10 Reply

      @Bolivar – waitfor also accepts Matlab handles. See http://www.mathworks.com/help/matlab/ref/waitfor.html. There is no need for any external package to use waitForDone.

  10. Bolivr Djamen October 14, 2013 at 12:31 Reply

    Thanks Yair , according to your reference it seem like just Graphic object can be given as argument to waitfor! actually I want to use it with common handle object defined with key word classdef

    • Yair Altman October 16, 2013 at 11:00 Reply

      I’m not sure that this is supported, but you are welcome to try. Please let us all know if it works for you.

  11. Daniel R May 18, 2014 at 16:39 Reply

    Hi Yair,
    I have a main GUI that calls several secondary GUIs and I’m using the uiwait function to hold the main window active but it disables the functionality of the command window and disables any other plots that i generate while its running for editing.

    I was wondering if you know of any way that the MATLAB command window can still be used while the uiwait function is being used to work with multiple GUI windows?

    • Yair Altman May 18, 2014 at 17:03 Reply

      @Daniel – no. You need to find an alternative to uiwait in your program if you need console interactivity. uiwait is designed for modality and what you request is not purely modal.

  12. Jan January 7, 2015 at 08:49 Reply

    Hi,
    the method that you proposed in the “Waiting for events on non-HG objects” does not seem to work anymore (2014b)
    I now get the following error:

    Error using waitfor
    Parameter must be scalar.

    Error using waitfor Parameter must be scalar.

    Can you confirm that this is indeed a problem in newer versions?

    Thanks
    Jan

    • Jan January 9, 2015 at 03:27 Reply

      I experimented a little bit.

      my goal is to block matlab execution until something in the java environment happens.
      for this i set a value in the java class to true. in an internal callback, this value changes to false
      if I pass my java class to the waitfor function like this:

      eventTest.setStartBlocked(true);
      waitfor(eventTest,'StartBlocked','off')

      eventTest.setStartBlocked(true); waitfor(eventTest,'StartBlocked','off')

      I get the following error message

      Error using waitfor
      Conversion to double from name.of.class is not possible.
      

      The error message I posted earlier occurs if I wrap my class with the handle command.

      waitfor will still wait for a figure, so maybe an ugly workaround would be using an invisible figure in some way?

      Maybe you have some better ideas

  13. William December 1, 2015 at 07:18 Reply

    About a year later, I second what Jan said. Matlab no longer allows non-scalar(able) objects passed into waitfor.

    I think you should update this article with a disclaimer that later versions of Matlab no longer support this behavior.

  14. Peter January 8, 2016 at 10:01 Reply

    Hi Yair,

    Is there a way to create a MATLAB function which works similar to waitforbuttonpress, except that it does not depend on a figure?

    I’m looking for a way for MATLAB to detect a mouse left-click anywhere on screen (not only inside a MATLAB figure or window).

  15. Marc Passy January 20, 2016 at 22:49 Reply

    Just a detailed point – waitfor now (as of 2015a) throws this error when using a handle that is not a Graphics object:

    Error using waitfor
    The input object must be a valid MATLAB Graphics object.

    Error using waitfor The input object must be a valid MATLAB Graphics object.

    I was trying to wait on a user-defined class that is a descendant of the built-in handle class.

    • Yair Altman January 20, 2016 at 22:57 Reply

      @Marc – however, you can still use waitfor with Java objects

  16. Marc January 21, 2016 at 00:19 Reply

    Related question. I’m coding up a simulation, and I’ve got a listener in one object that is dependent on the completion of the listener in another object. (This is not gui work). They are both listening to the same event from the same object. In the dependent class, I tried busy-waiting (with a pause, of course), and it seems that no matter what I do, those two callbacks execute sequentially.

    based on this, I presume that matlab is executing all of these callbacks in a single thread, and the dispatcher for the event source is just executing the listeners in order, so that it can’t process the next until the prior one returns?

    • Yair Altman January 21, 2016 at 00:23 Reply

      This is not surprising. Matlab’s computational engine is [still] single threaded. I hope and expect this will change in the future. Even when it does, I’m not sure that the listeners would be dispatched asynchronously. I can think of quite a few use-cases where the synchronous listener invocation is actually intended.

  17. Johan February 1, 2016 at 03:41 Reply

    Hi Yair,

    I stumbled onto this page when trying to solve my conundrum. I’m trying to get ‘waitfor/uiwait’ to hold for a message box in a callback. I made a minimum working example like this:

    function foo()
    uicontrol('style','push','string','push','callback',@cbf,'parent',figure);
     
    function cbf(~,~)
    h = msgbox('press ok to continue');
    waitfor(h)

    function foo() uicontrol('style','push','string','push','callback',@cbf,'parent',figure); function cbf(~,~) h = msgbox('press ok to continue'); waitfor(h)

    But no matter what I do, the waitfor is not respected, that is the pushbutton is not blocked so one can open as many msgboxes as one likes. Very odd behaviour I think, have you by any chance encountered issues like this before?

    • Yair Altman February 1, 2016 at 12:45 Reply

      The code that is launched by the button callback runs on a separate thread so waitfor simply blocks execution of that thread, and other callbacks can still process. This is actually documented in waitfor‘s documentation. I suggest to modify the callback code by disabling the button to prevent additional button clicks while one callback is blocked:

      function cbf(hButton,~)
        set(hButton,'Enable','off');
        waitfor(msgbox(...))
        set(hButton,'Enable','on');
      end

      function cbf(hButton,~) set(hButton,'Enable','off'); waitfor(msgbox(...)) set(hButton,'Enable','on'); end

  18. Episode 001 – Handling Matlab interrupts in Java – v1ntage.io July 1, 2017 at 06:52 Reply

    […] that is currently blocked forever inside the Java method. This problem has come up again, and again, and again over the […]

  19. Brian July 16, 2017 at 07:10 Reply

    Hey I know this is a rather old post, but I wanted to post my solution just in case anyone from the future has the same question. It turns out you can call back into Matlab via JMI to poll the keyboard event queue and trigger an exception if a “Ctrl-C” is waiting. I wrote this up in more detail on my blog at https://v1ntage.io/2017/07/01/episode-001-handling-matlab-interrupts-in-java/. Let me know what you think.

    • Yair Altman March 30, 2018 at 12:15 Reply

      I discussed Ctrl-C interrupts here: http://undocumentedmatlab.com/blog/mex-ctrl-c-interrupt

  20. Ben A. September 29, 2017 at 19:55 Reply

    Hey Yair,
    These solutions have proven to be invaluable for me, but sometimes don’t work well for complicated asynchronous situations. I have found an additional approach that has worked very well for me so far.
    Python (which we can call natively in MATLAB) has a threading module with an Event object that works easily and reliably. Creating the Event object is just a matter of calling:

    myevent = py.threading.Event();

    myevent = py.threading.Event();

    And then making the object available to all interested parties (through appdata, parameter passing, etc.).
    The object’s set(), is_set(), clear(), and wait() functions work quickly and reliably in MATLAB, and the wait() function takes a timeout parameter and returns a Boolean value that is true unless the timeout was reached.

    • Yair Altman March 30, 2018 at 12:19 Reply

      Unfortunately, using the Python object requires a separate installation of Python. While it is true that many users already have Python installed, many others do not and for such users the Python solution will error. In contrast, the solution that I presented above is based on the built-in waitfor function, and therefore works for all users.

Leave a Reply
HTML tags such as <b> or <i> are accepted.
Wrap code fragments inside <pre lang="matlab"> tags, like this:
<pre lang="matlab">
a = magic(3);
disp(sum(a))
</pre>
I reserve the right to edit/delete comments (read the site policies).
Not all comments will be answered. You can always email me (altmany at gmail) for private consulting.

Click here to cancel reply.

Useful links
  •  Email Yair Altman
  •  Subscribe to new posts (feed)
  •  Subscribe to new posts (reader)
  •  Subscribe to comments (feed)
 
Accelerating MATLAB Performance book
Recent Posts

Speeding-up builtin Matlab functions – part 3

Improving graphics interactivity

Interesting Matlab puzzle – analysis

Interesting Matlab puzzle

Undocumented plot marker types

Matlab toolstrip – part 9 (popup figures)

Matlab toolstrip – part 8 (galleries)

Matlab toolstrip – part 7 (selection controls)

Matlab toolstrip – part 6 (complex controls)

Matlab toolstrip – part 5 (icons)

Matlab toolstrip – part 4 (control customization)

Reverting axes controls in figure toolbar

Matlab toolstrip – part 3 (basic customization)

Matlab toolstrip – part 2 (ToolGroup App)

Matlab toolstrip – part 1

Categories
  • Desktop (45)
  • Figure window (59)
  • Guest bloggers (65)
  • GUI (165)
  • Handle graphics (84)
  • Hidden property (42)
  • Icons (15)
  • Java (174)
  • Listeners (22)
  • Memory (16)
  • Mex (13)
  • Presumed future risk (394)
    • High risk of breaking in future versions (100)
    • Low risk of breaking in future versions (160)
    • Medium risk of breaking in future versions (136)
  • Public presentation (6)
  • Semi-documented feature (10)
  • Semi-documented function (35)
  • Stock Matlab function (140)
  • Toolbox (10)
  • UI controls (52)
  • Uncategorized (13)
  • Undocumented feature (217)
  • Undocumented function (37)
Tags
AppDesigner (9) Callbacks (31) Compiler (10) Desktop (38) Donn Shull (10) Editor (8) Figure (19) FindJObj (27) GUI (141) GUIDE (8) Handle graphics (78) HG2 (34) Hidden property (51) HTML (26) Icons (9) Internal component (39) Java (178) JavaFrame (20) JIDE (19) JMI (8) Listener (17) Malcolm Lidierth (8) MCOS (11) Memory (13) Menubar (9) Mex (14) Optical illusion (11) Performance (78) Profiler (9) Pure Matlab (187) schema (7) schema.class (8) schema.prop (18) Semi-documented feature (6) Semi-documented function (33) Toolbar (14) Toolstrip (13) uicontrol (37) uifigure (8) UIInspect (12) uitable (6) uitools (20) Undocumented feature (187) Undocumented function (37) Undocumented property (20)
Recent Comments
Contact us
Captcha image for Custom Contact Forms plugin. You must type the numbers shown in the image
Undocumented Matlab © 2009 - Yair Altman
This website and Octahedron Ltd. are not affiliated with The MathWorks Inc.; MATLAB® is a registered trademark of The MathWorks Inc.
Scroll to top