diff --git a/fsl/utils/async.py b/fsl/utils/async.py
index 61e5aca90f47b4f4c6f61d9aa255116ee943c63a..9c3487c945de12b7115bba7e4b0fd3b393071c28 100644
--- a/fsl/utils/async.py
+++ b/fsl/utils/async.py
@@ -96,14 +96,6 @@ except: import Queue as queue
 log = logging.getLogger(__name__)
 
 
-def _haveWX():
-    """Returns ``True`` if we are running within a ``wx`` application,
-    ``False`` otherwise.
-    """
-    import fsl.utils.platform as fslplatform
-    return fslplatform.platform.haveGui
-
-
 def run(task, onFinish=None, onError=None, name=None):
     """Run the given ``task`` in a separate thread.
 
@@ -125,10 +117,12 @@ def run(task, onFinish=None, onError=None, name=None):
               the return value will be ``None``.
     """
 
+    from fsl.utils.platform import platform as fslplatform
+
     if name is None:
         name = getattr(task, '__name__', '<unknown>')
 
-    haveWX = _haveWX()
+    haveWX = fslplatform.haveGui
 
     # Calls the onFinish or onError handler
     def callback(cb, *args, **kwargs):
@@ -397,9 +391,11 @@ def idle(task, *args, **kwargs):
                        argument. If ``True``, and a ``wx.MainLoop`` is not
                        running, the task is enqueued anyway, under the
                        assumption that a ``wx.MainLoop`` will be started in
-                       the future. Note that another  call to ``idle`` must
-                       be made after the ``MainLoop`` has started for the
-                       original task to be executed.
+                       the future. Note that, if ``wx.App`` has not yet been
+                       created, another  call to ``idle`` must be made after
+                       the app has been created for the original task to be
+                       executed. If ``wx`` is not available, this parameter
+                       will be ignored, and the task executed directly.
 
 
     All other arguments are passed through to the task function.
@@ -426,6 +422,8 @@ def idle(task, *args, **kwargs):
               ``alwaysQueue``.
     """
 
+    from fsl.utils.platform import platform as fslplatform
+
     global _idleRegistered
     global _idleTimer
     global _idleQueue
@@ -439,13 +437,29 @@ def idle(task, *args, **kwargs):
     skipIfQueued = kwargs.pop('skipIfQueued', False)
     alwaysQueue  = kwargs.pop('alwaysQueue',  False)
 
-    havewx       = _haveWX()
+    canHaveGui = fslplatform.canHaveGui
+    haveGui    = fslplatform.haveGui
+
+    # If there is no possibility of a
+    # gui being available in the future,
+    # then alwaysQueue is ignored.
+    if haveGui or (alwaysQueue and canHaveGui):
 
-    if havewx or alwaysQueue:
         import wx
+        app = wx.GetApp()
+
+        # Register on the idle event
+        # if an app is available
+        #
+        # n.b. The 'app is not None' test will
+        # potentially fail in scenarios where
+        # multiple wx.Apps have been instantiated,
+        # as it may return a previously created
+        # app.
+        if (not _idleRegistered) and (app is not None):
+
+            log.debug('Registering async idle loop')
 
-        if havewx and (not _idleRegistered):
-            app = wx.GetApp()
             app.Bind(wx.EVT_IDLE, _wxIdleLoop)
             
             _idleTimer      = wx.Timer(app)
@@ -546,12 +560,14 @@ def wait(threads, task, *args, **kwargs):
               a keyword argument called ``wait_direct``.
     """
 
+    from fsl.utils.platform import platform as fslplatform
+
     direct = kwargs.pop('wait_direct', False)
 
     if not isinstance(threads, collections.Sequence):
         threads = [threads]
-    
-    haveWX = _haveWX()
+
+    haveWX = fslplatform.haveGui
 
     def joinAll():
         log.debug('Wait thread joining on all targets')