Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
fslpy
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Container Registry
Model registry
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Michiel Cottaar
fslpy
Commits
cfac8139
Commit
cfac8139
authored
8 years ago
by
Paul McCarthy
Browse files
Options
Downloads
Patches
Plain Diff
New thing in async module - the TaskThread, a simple task queue.
parent
975d1c75
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
fsl/utils/async.py
+149
-9
149 additions, 9 deletions
fsl/utils/async.py
with
149 additions
and
9 deletions
fsl/utils/async.py
+
149
−
9
View file @
cfac8139
...
...
@@ -4,12 +4,40 @@
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""
This module provides functions for running tasks asynchronously.
"""
This module provides functions and classes for running tasks
asynchronously, either in an idle loop, or on a separate thread.
.. note:: The functions in this module are intended to be run from within a
``wx`` application. However, they will still work without ``wx``,
albeit with slightly modified behaviour.
.. note:: The *idle* functions in this module are intended to be run from
within a ``wx`` application. However, they will still work without
``wx``, albeit with slightly modified behaviour.
Idle tasks
----------
.. autosummary::
:nosignatures:
idle
inIdle
The :func:`idle` function is a simple way to run a task on an ``wx``
``EVT_IDLE`` event handler. This effectively performs the same job as the
:func:`run` function, but is more suitable for short tasks which do not
warrant running in a separate thread.
Thread tasks
------------
.. autosummary::
:nosignatures:
run
wait
TaskThread
The :func:`run` function simply runs a task in a separate thread. This
...
...
@@ -21,15 +49,14 @@ intensitve task off the main GUI thread (preventing the GUI from locking up),
and to perform some clean up/refresh afterwards.
The :func:`idle` function is a simple way to run a task on an ``wx``
``EVT_IDLE`` event handler. This effectively performs the same job as the
:func:`run` function, but is more suitable for short tasks which do not
warrant running in a separate thread.
The :func:`wait` function is given one or more ``Thread`` instances, and a
task to run. It waits until all the threads have finished, and then runs
the task (via :func:`idle`).
The :class:`TaskThread` class is a simple thread which runs a queue of tasks.
.. todo:: You could possibly use ``props.callqueue`` to drive the idle loop.
"""
...
...
@@ -324,3 +351,116 @@ def wait(threads, task, *args, **kwargs):
else
:
joinAll
()
return
None
class
Task
(
object
):
"""
Container object which encapsulates a task that is run by a
:class:`TaskThread`.
"""
def
__init__
(
self
,
name
,
func
,
args
,
kwargs
):
self
.
name
=
name
self
.
func
=
func
self
.
args
=
args
self
.
kwargs
=
kwargs
self
.
enabled
=
True
class
TaskThread
(
threading
.
Thread
):
"""
The ``TaskThread`` is a simple thread which runs tasks. Tasks may be
enqueued and dequeued.
.. note::
"""
def
__init__
(
self
,
*
args
,
**
kwargs
):
"""
Create a ``TaskThread``
"""
threading
.
Thread
.
__init__
(
self
,
*
args
,
**
kwargs
)
self
.
__q
=
queue
.
Queue
()
self
.
__enqueued
=
{}
self
.
__stop
=
False
log
.
debug
(
'
New task thread
'
)
def
enqueue
(
self
,
name
,
func
,
*
args
,
**
kwargs
):
"""
Enqueue a task to be executed.
:arg name: Task name. Does not necessarily have to be a string,
but must be hashable.
:arg func: The task function.
All other arguments will be passed through to the task when it is
executed.
"""
log
.
debug
(
'
Enqueueing task: {} [{}]
'
.
format
(
name
,
getattr
(
func
,
'
__name__
'
,
'
<unknown>
'
)))
t
=
Task
(
name
,
func
,
args
,
kwargs
)
self
.
__enqueued
[
name
]
=
t
self
.
__q
.
put
(
t
)
def
isQueued
(
self
,
name
):
"""
Returns ``True`` if a task with the given name is enqueued,
``False`` otherwise.
"""
return
name
in
self
.
__enqueued
def
dequeue
(
self
,
name
):
"""
Dequeues a previously enqueued task.
:arg name: The task to dequeue.
"""
task
=
self
.
__enqueued
.
get
(
name
,
None
)
if
task
is
not
None
:
log
.
debug
(
'
Dequeueing task: {}
'
.
format
(
name
))
task
.
enabled
=
False
def
stop
(
self
):
"""
Stop the ``TaskThread`` after any currently running task has
completed.
"""
log
.
debug
(
'
Stopping task thread
'
)
self
.
__stop
=
True
def
run
(
self
):
"""
Run the ``TaskThread``.
"""
while
True
:
try
:
task
=
self
.
__q
.
get
(
timeout
=
1
)
except
queue
.
Empty
:
continue
finally
:
if
self
.
__stop
:
break
self
.
__enqueued
.
pop
(
task
.
name
,
None
)
if
not
task
.
enabled
:
continue
log
.
debug
(
'
Running task: {} [{}]
'
.
format
(
task
.
name
,
getattr
(
task
.
func
,
'
__name__
'
,
'
<unknown>
'
)))
task
.
func
(
*
task
.
args
,
**
task
.
kwargs
)
log
.
debug
(
'
Task completed: {} [{}]
'
.
format
(
task
.
name
,
getattr
(
task
.
func
,
'
__name__
'
,
'
<unknown>
'
)))
self
.
__q
=
None
self
.
__enqueued
=
None
log
.
debug
(
'
Task thread finished
'
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment