diff --git a/docs/source/traits_user_manual/notification.rst b/docs/source/traits_user_manual/notification.rst index 75889befa..13ca695df 100644 --- a/docs/source/traits_user_manual/notification.rst +++ b/docs/source/traits_user_manual/notification.rst @@ -257,8 +257,20 @@ Notification Handler -------------------- By default, the **handler** is invoked immediately after the change has -occurred. The **dispatch** parameter in |@observe| can be set such that the -handler is dispatched elsewhere to be invoked later (e.g. on a GUI event loop). +occurred. This behaviour can be changed using the **dispatch** parameter +to the |@observe| method. + +The |@observe| method currently supports two values for the **dispatch** +parameter: ``"same"`` and ``"ui"``. ``dispatch="same"`` corresponds to the +default behaviour. When using ``dispatch="ui"``, the behaviour depends on the +thread that triggered the observer. If the change that triggers the observer +occurs on the main thread then the behaviour is the same as +``dispatch="same"``: the observer is called immediately. However, if the change +occurs on a thread other than the main thread then the observer is scheduled to +be called on the UI thread, using the UI handler (if any) that has been set by +the function :func:`~.set_ui_handler`. (Note: in normal use, this handler is +set by Pyface as part of GUI selection; it's rare that the user needs to call +:func:`~.set_ui_handler` directly.) The following expectations apply to any change handler: diff --git a/traits/tests/test_trait_notifiers.py b/traits/tests/test_trait_notifiers.py new file mode 100644 index 000000000..f03f3b471 --- /dev/null +++ b/traits/tests/test_trait_notifiers.py @@ -0,0 +1,42 @@ +# (C) Copyright 2005-2023 Enthought, Inc., Austin, TX +# All rights reserved. +# +# This software is provided without warranty under the terms of the BSD +# license included in LICENSE.txt and may be redistributed only under +# the conditions described in the aforementioned license. The license +# is also available online at http://www.enthought.com/licenses/BSD.txt +# +# Thanks for using Enthought open source! + +import unittest + +from traits.api import HasTraits, Int + + +class TestTraitNotifiers(unittest.TestCase): + def test_ui_dispatch(self): + # Given + class DispatchTest(HasTraits): + test_param = Int() + + t = DispatchTest() + + event_list = [] + + # create handler + def test_handler(event): + event_list.append(event) + + # When + t.observe(test_handler, "test_param", dispatch="ui") + t.test_param = 1 + + # Then + # check the observer is called once + self.assertEqual(len(event_list), 1) + # check the name of the parameter change + self.assertEqual(event_list[0].name, "test_param") + # check whether the value starts at 0 + self.assertEqual(event_list[0].old, 0) + # check whether the value has been set to 1 + self.assertEqual(event_list[0].new, 1) diff --git a/traits/trait_notifiers.py b/traits/trait_notifiers.py index 6ebf692d0..fcd114eca 100644 --- a/traits/trait_notifiers.py +++ b/traits/trait_notifiers.py @@ -44,7 +44,7 @@ def set_ui_handler(handler): def ui_dispatch(handler, *args, **kw): - if threading.current_thread().ident == ui_thread: + if threading.current_thread() == threading.main_thread(): handler(*args, **kw) else: ui_handler(handler, *args, **kw)