We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Change in label text doesn't trigger rehint and relayout
**Describe the bug**
Using `yield` in a function that gets triggered from an buttons `on_press` event is not responding on Windows.

**To Reproduce**
Steps to reproduce the behavior:
1. Click Button
2. See No Change

**Expected behavior**
The label should show "RUN1" and after 5s change to "RUN2"

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Environment:**
 - Operating System: Linux
 - Python version: 3.9
 - Software versions:
   - Briefcase: 0.3.3 
   - Toga: 0.3.0.dev25
**Additional context**
The Installer is build with the following file:
```

# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Windows

on:
  push:
    branches: [ master, workflow-test, app-path, windows-yield ]
  pull_request:
    branches: [ master ]

jobs:
  build:

    runs-on: windows-latest

    steps:
    - uses: actions/checkout@v2
    - name: Set up Python 3.8
      uses: actions/setup-python@v2
      with:
        python-version: 3.8
    - name: Install dependencies
      run: |
        #apt-get update
        #sudo apt-get install git python3-dev python3-pip libgirepository1.0-dev libcairo2-dev libpango1.0-dev libwebkitgtk-3.0-0 gir1.2-webkit-3.0
    - name: Beeware dependencies
      run: |
        # stop the build if there are Python syntax errors or undefined names
        python -m pip install beeware
        python -m pip install dhooks
    - name: Run tests with pytest
      run: |
        cd src/
        python -m unittest test_app.Test_Profile_Manager.test_swap_xml -v
        python -m unittest test_app.Test_Profile_Manager.test_delete_profile -v
        python -m unittest test_app.Test_Profile_Manager.test_create_profile -v
        python -m unittest test_app.Test_Profile_Manager.test_load_profile -v
        python -m unittest test_app.Test_Profile_Manager.test_get_ethnic -v
        python -m unittest test_app.Test_Profile_Manager.test_switching_profiles_with_invalid_path -v
        python -m unittest test_app.Test_Profile_Manager.test_migrate_function -v
        python -m unittest test_app.Test_XML_Parser -v
        python -m unittest test_app.Test_RTF_Parser -v
        python -m unittest test_app.Test_Config_Manager -v
        python -m unittest test_app.Test_Xml_Writing -v
        python -m unittest test_mapper.Test_Mapper_Generate_Mapping -v
        python -m unittest test_mapper.Test_Mapper_Preserve_Mapping -v
        python -m unittest test_mapper.Test_Mapper_Overwrite_Mapping -v
    - name: Build
      run: |
        briefcase create
        briefcase build
        briefcase package
    - name: Save Installer
      uses: actions/upload-artifact@v1
      with:
        name: NewGAN-Manager-Installer-Win
        path: windows\NewGAN Manager-1.1.0.msi
```

The `app.py`
```
"""
Yield Test
"""
import toga
import time


class NewGANManager(toga.App):

    def startup(self):
        self.main_window = toga.MainWindow(self.name)
        self.output = toga.Label("")
        self.btn = toga.Button(label="Run", on_press=self.calc)
        self.main_box = toga.Box()
        self.main_box.add(self.output)
        self.main_box.add(self.btn)
        self.main_window.content = self.main_box
        self.main_window.show()
    def calc(self, widget):
        self.output.text = "RUN1"
        yield 0.1
        time.sleep(3)
        self.output.text = "RUN2"
        yield 0.1

def main():
    return NewGANManager('Toga Demo', 'org.beeware.toga-demo')
```

more info here: https://github.com/Maradonna90/NewGAN-Manager/tree/windows-yield

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/winforms/toga_winforms/libs/proactor.py`
Content:
```
1 import asyncio
2 import sys
3 import threading
4 from asyncio import events
5 
6 from .winforms import Action, Task, WinForms, user32
7 
8 
9 class AsyncIOTickMessageFilter(WinForms.IMessageFilter):
10     """
11     A Winforms message filter that will catch the request to tick the Asyncio
12     event loop.
13     """
14     __namespace__ = 'System.Windows.Forms'
15 
16     def __init__(self, loop, msg_id):
17         self.loop = loop
18         self.msg_id = msg_id
19 
20     def PreFilterMessage(self, message):
21         print('ping', message)
22         if message.Msg == self.msg_id:
23             print("asyncio tick message!!")
24             self.loop.run_once_recurring()
25             return True
26         # print("Filter message", message)
27         return False
28 
29 
30 class WinformsProactorEventLoop(asyncio.ProactorEventLoop):
31     def run_forever(self, app_context):
32         """Set up the asyncio event loop, integrate it with the Winforms
33         event loop, and start the application.
34 
35         This largely duplicates the setup behavior of the default Proactor
36         run_forever implementation.
37 
38         :param app_context: The WinForms.ApplicationContext instance
39             controlling the lifecycle of the app.
40         """
41         # Python 3.8 added an implementation of run_forever() in
42         # ProactorEventLoop. The only part that actually matters is the
43         # refactoring that moved the initial call to stage _loop_self_reading;
44         # it now needs to be created as part of run_forever; otherwise the
45         # event loop locks up, because there won't be anything for the
46         # select call to process.
47         if sys.version_info >= (3, 8):
48             self.call_soon(self._loop_self_reading)
49 
50         # Remember the application context.
51         self.app_context = app_context
52 
53         # Register a custom user window message.
54         self.msg_id = user32.RegisterWindowMessageA("Python asyncio tick")
55         # Add a message filter to listen for the asyncio tick message
56         # FIXME: Actually install the message filter.
57         # msg_filter = AsyncIOTickMessageFilter(self, self.msg_id)
58         # WinForms.Application.AddMessageFilter(msg_filter)
59 
60         # Setup the Proactor.
61         # The code between the following markers should be exactly the same as
62         # the official CPython implementation, up to the start of the
63         # `while True:` part of run_forever() (see BaseEventLoop.run_forever()
64         # in Lib/ascynio/base_events.py)
65         # === START BaseEventLoop.run_forever() setup ===
66         self._check_closed()
67         if self.is_running():
68             raise RuntimeError('This event loop is already running')
69         if events._get_running_loop() is not None:
70             raise RuntimeError(
71                 'Cannot run the event loop while another loop is running')
72         self._set_coroutine_origin_tracking(self._debug)
73         self._thread_id = threading.get_ident()
74         try:
75             self._old_agen_hooks = sys.get_asyncgen_hooks()
76             sys.set_asyncgen_hooks(
77                 firstiter=self._asyncgen_firstiter_hook,
78                 finalizer=self._asyncgen_finalizer_hook
79             )
80         except AttributeError:
81             # Python < 3.6 didn't have sys.get_asyncgen_hooks();
82             # No action required for those versions.
83             pass
84 
85         events._set_running_loop(self)
86         # === END BaseEventLoop.run_forever() setup ===
87 
88         # Rather than going into a `while True:` loop, we're going to use the
89         # Winforms event loop to queue a tick() message that will cause a
90         # single iteration of the asyncio event loop to be executed. Each time
91         # we do this, we queue *another* tick() message in 5ms time. In this
92         # way, we'll get a continuous stream of tick() calls, without blocking
93         # the Winforms event loop.
94 
95         # Queue the first asyncio tick.
96         self.enqueue_tick()
97 
98         # Start the Winforms event loop.
99         WinForms.Application.Run(self.app_context)
100 
101     def enqueue_tick(self):
102         # Queue a call to tick in 5ms.
103         self.task = Action[Task](self.tick)
104         Task.Delay(5).ContinueWith(self.task)
105 
106     def tick(self, *args, **kwargs):
107         """
108         Cause a single iteration of the event loop to run on the main GUI thread.
109         """
110         # Post a userspace message that will trigger running an iteration
111         # of the asyncio event loop. This can't be done directly, because the
112         # tick() will be executing in a threadpool, and we need the asyncio
113         # handling to occur in the main GUI thread. However, by positing a
114         # message, it will be caught by the MessageFilter we installed on the
115         # Application thread.
116 
117         if self.task:
118             self.task.Dispose()
119             del self.task
120         # The message is sent with:
121         # * HWND 0xfff (all windows),
122         # * MSG self.msg_id (a message ID in the WM_USER range)
123         # * LPARAM and WPARAM empty (no extra details needed; just tick!)
124         user32.PostMessageA(0xffff, self.msg_id, None, None)
125 
126         # FIXME: Once we have a working message filter, this invoke call
127         # can be removed.
128         # If the app context has a main form, invoke run_once_recurring()
129         # on the thread associated with that form.
130         if self.app_context.MainForm:
131             action = Action(self.run_once_recurring)
132             self.app_context.MainForm.Invoke(action)
133             action.Dispose()
134             del action
135 
136     def run_once_recurring(self):
137         """
138         Run one iteration of the event loop, and enqueue the next iteration
139         (if we're not stopping).
140 
141         This largely duplicates the "finally" behavior of the default Proactor
142         run_forever implementation.
143         """
144         # Perform one tick of the event loop.
145         self._run_once()
146 
147         if self._stopping:
148             # If we're stopping, we can do the "finally" handling from
149             # the BaseEventLoop run_forever().
150             # === START BaseEventLoop.run_forever() finally handling ===
151             self._stopping = False
152             self._thread_id = None
153             events._set_running_loop(None)
154             self._set_coroutine_origin_tracking(False)
155             try:
156                 sys.set_asyncgen_hooks(*self._old_agen_hooks)
157             except AttributeError:
158                 # Python < 3.6 didn't have set_asyncgen_hooks.
159                 # No action required for those versions.
160                 pass
161             # === END BaseEventLoop.run_forever() finally handling ===
162         else:
163             # Otherwise, live to tick another day. Enqueue the next tick,
164             # and make sure there will be *something* to be processed.
165             # If you don't ensure there is at least one message on the
166             # queue, the select() call will block, locking the app.
167             self.enqueue_tick()
168             self.call_soon(self._loop_self_reading)
169 
170 
171 # Python 3.7 changed the name of an internal wrapper function.
172 # Install an alias for the old name at the new name.
173 if sys.version_info < (3, 7):
174     WinformsProactorEventLoop._set_coroutine_origin_tracking = WinformsProactorEventLoop._set_coroutine_wrapper
175
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/winforms/toga_winforms/libs/proactor.py b/src/winforms/toga_winforms/libs/proactor.py
--- a/src/winforms/toga_winforms/libs/proactor.py
+++ b/src/winforms/toga_winforms/libs/proactor.py
@@ -114,9 +114,6 @@
         # message, it will be caught by the MessageFilter we installed on the
         # Application thread.
 
-        if self.task:
-            self.task.Dispose()
-            del self.task
         # The message is sent with:
         # * HWND 0xfff (all windows),
         # * MSG self.msg_id (a message ID in the WM_USER range)
@@ -130,8 +127,6 @@
         if self.app_context.MainForm:
             action = Action(self.run_once_recurring)
             self.app_context.MainForm.Invoke(action)
-            action.Dispose()
-            del action
 
     def run_once_recurring(self):
         """

{"golden_diff": "diff --git a/src/winforms/toga_winforms/libs/proactor.py b/src/winforms/toga_winforms/libs/proactor.py\n--- a/src/winforms/toga_winforms/libs/proactor.py\n+++ b/src/winforms/toga_winforms/libs/proactor.py\n@@ -114,9 +114,6 @@\n         # message, it will be caught by the MessageFilter we installed on the\n         # Application thread.\n \n-        if self.task:\n-            self.task.Dispose()\n-            del self.task\n         # The message is sent with:\n         # * HWND 0xfff (all windows),\n         # * MSG self.msg_id (a message ID in the WM_USER range)\n@@ -130,8 +127,6 @@\n         if self.app_context.MainForm:\n             action = Action(self.run_once_recurring)\n             self.app_context.MainForm.Invoke(action)\n-            action.Dispose()\n-            del action\n \n     def run_once_recurring(self):\n         \"\"\"\n", "issue": "Change in label text doesn't trigger rehint and relayout\n**Describe the bug**\r\nUsing `yield` in a function that gets triggered from an buttons `on_press` event is not responding on Windows.\r\n\r\n**To Reproduce**\r\nSteps to reproduce the behavior:\r\n1. Click Button\r\n2. See No Change\r\n\r\n**Expected behavior**\r\nThe label should show \"RUN1\" and after 5s change to \"RUN2\"\r\n\r\n**Screenshots**\r\nIf applicable, add screenshots to help explain your problem.\r\n\r\n**Environment:**\r\n - Operating System: Linux\r\n - Python version: 3.9\r\n - Software versions:\r\n   - Briefcase: 0.3.3 \r\n   - Toga: 0.3.0.dev25\r\n**Additional context**\r\nThe Installer is build with the following file:\r\n```\r\n\r\n# This workflow will install Python dependencies, run tests and lint with a single version of Python\r\n# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions\r\n\r\nname: Windows\r\n\r\non:\r\n  push:\r\n    branches: [ master, workflow-test, app-path, windows-yield ]\r\n  pull_request:\r\n    branches: [ master ]\r\n\r\njobs:\r\n  build:\r\n\r\n    runs-on: windows-latest\r\n\r\n    steps:\r\n    - uses: actions/checkout@v2\r\n    - name: Set up Python 3.8\r\n      uses: actions/setup-python@v2\r\n      with:\r\n        python-version: 3.8\r\n    - name: Install dependencies\r\n      run: |\r\n        #apt-get update\r\n        #sudo apt-get install git python3-dev python3-pip libgirepository1.0-dev libcairo2-dev libpango1.0-dev libwebkitgtk-3.0-0 gir1.2-webkit-3.0\r\n    - name: Beeware dependencies\r\n      run: |\r\n        # stop the build if there are Python syntax errors or undefined names\r\n        python -m pip install beeware\r\n        python -m pip install dhooks\r\n    - name: Run tests with pytest\r\n      run: |\r\n        cd src/\r\n        python -m unittest test_app.Test_Profile_Manager.test_swap_xml -v\r\n        python -m unittest test_app.Test_Profile_Manager.test_delete_profile -v\r\n        python -m unittest test_app.Test_Profile_Manager.test_create_profile -v\r\n        python -m unittest test_app.Test_Profile_Manager.test_load_profile -v\r\n        python -m unittest test_app.Test_Profile_Manager.test_get_ethnic -v\r\n        python -m unittest test_app.Test_Profile_Manager.test_switching_profiles_with_invalid_path -v\r\n        python -m unittest test_app.Test_Profile_Manager.test_migrate_function -v\r\n        python -m unittest test_app.Test_XML_Parser -v\r\n        python -m unittest test_app.Test_RTF_Parser -v\r\n        python -m unittest test_app.Test_Config_Manager -v\r\n        python -m unittest test_app.Test_Xml_Writing -v\r\n        python -m unittest test_mapper.Test_Mapper_Generate_Mapping -v\r\n        python -m unittest test_mapper.Test_Mapper_Preserve_Mapping -v\r\n        python -m unittest test_mapper.Test_Mapper_Overwrite_Mapping -v\r\n    - name: Build\r\n      run: |\r\n        briefcase create\r\n        briefcase build\r\n        briefcase package\r\n    - name: Save Installer\r\n      uses: actions/upload-artifact@v1\r\n      with:\r\n        name: NewGAN-Manager-Installer-Win\r\n        path: windows\\NewGAN Manager-1.1.0.msi\r\n```\r\n\r\nThe `app.py`\r\n```\r\n\"\"\"\r\nYield Test\r\n\"\"\"\r\nimport toga\r\nimport time\r\n\r\n\r\nclass NewGANManager(toga.App):\r\n\r\n    def startup(self):\r\n        self.main_window = toga.MainWindow(self.name)\r\n        self.output = toga.Label(\"\")\r\n        self.btn = toga.Button(label=\"Run\", on_press=self.calc)\r\n        self.main_box = toga.Box()\r\n        self.main_box.add(self.output)\r\n        self.main_box.add(self.btn)\r\n        self.main_window.content = self.main_box\r\n        self.main_window.show()\r\n    def calc(self, widget):\r\n        self.output.text = \"RUN1\"\r\n        yield 0.1\r\n        time.sleep(3)\r\n        self.output.text = \"RUN2\"\r\n        yield 0.1\r\n\r\ndef main():\r\n    return NewGANManager('Toga Demo', 'org.beeware.toga-demo')\r\n```\r\n\r\nmore info here: https://github.com/Maradonna90/NewGAN-Manager/tree/windows-yield\n", "before_files": [{"content": "import asyncio\nimport sys\nimport threading\nfrom asyncio import events\n\nfrom .winforms import Action, Task, WinForms, user32\n\n\nclass AsyncIOTickMessageFilter(WinForms.IMessageFilter):\n    \"\"\"\n    A Winforms message filter that will catch the request to tick the Asyncio\n    event loop.\n    \"\"\"\n    __namespace__ = 'System.Windows.Forms'\n\n    def __init__(self, loop, msg_id):\n        self.loop = loop\n        self.msg_id = msg_id\n\n    def PreFilterMessage(self, message):\n        print('ping', message)\n        if message.Msg == self.msg_id:\n            print(\"asyncio tick message!!\")\n            self.loop.run_once_recurring()\n            return True\n        # print(\"Filter message\", message)\n        return False\n\n\nclass WinformsProactorEventLoop(asyncio.ProactorEventLoop):\n    def run_forever(self, app_context):\n        \"\"\"Set up the asyncio event loop, integrate it with the Winforms\n        event loop, and start the application.\n\n        This largely duplicates the setup behavior of the default Proactor\n        run_forever implementation.\n\n        :param app_context: The WinForms.ApplicationContext instance\n            controlling the lifecycle of the app.\n        \"\"\"\n        # Python 3.8 added an implementation of run_forever() in\n        # ProactorEventLoop. The only part that actually matters is the\n        # refactoring that moved the initial call to stage _loop_self_reading;\n        # it now needs to be created as part of run_forever; otherwise the\n        # event loop locks up, because there won't be anything for the\n        # select call to process.\n        if sys.version_info >= (3, 8):\n            self.call_soon(self._loop_self_reading)\n\n        # Remember the application context.\n        self.app_context = app_context\n\n        # Register a custom user window message.\n        self.msg_id = user32.RegisterWindowMessageA(\"Python asyncio tick\")\n        # Add a message filter to listen for the asyncio tick message\n        # FIXME: Actually install the message filter.\n        # msg_filter = AsyncIOTickMessageFilter(self, self.msg_id)\n        # WinForms.Application.AddMessageFilter(msg_filter)\n\n        # Setup the Proactor.\n        # The code between the following markers should be exactly the same as\n        # the official CPython implementation, up to the start of the\n        # `while True:` part of run_forever() (see BaseEventLoop.run_forever()\n        # in Lib/ascynio/base_events.py)\n        # === START BaseEventLoop.run_forever() setup ===\n        self._check_closed()\n        if self.is_running():\n            raise RuntimeError('This event loop is already running')\n        if events._get_running_loop() is not None:\n            raise RuntimeError(\n                'Cannot run the event loop while another loop is running')\n        self._set_coroutine_origin_tracking(self._debug)\n        self._thread_id = threading.get_ident()\n        try:\n            self._old_agen_hooks = sys.get_asyncgen_hooks()\n            sys.set_asyncgen_hooks(\n                firstiter=self._asyncgen_firstiter_hook,\n                finalizer=self._asyncgen_finalizer_hook\n            )\n        except AttributeError:\n            # Python < 3.6 didn't have sys.get_asyncgen_hooks();\n            # No action required for those versions.\n            pass\n\n        events._set_running_loop(self)\n        # === END BaseEventLoop.run_forever() setup ===\n\n        # Rather than going into a `while True:` loop, we're going to use the\n        # Winforms event loop to queue a tick() message that will cause a\n        # single iteration of the asyncio event loop to be executed. Each time\n        # we do this, we queue *another* tick() message in 5ms time. In this\n        # way, we'll get a continuous stream of tick() calls, without blocking\n        # the Winforms event loop.\n\n        # Queue the first asyncio tick.\n        self.enqueue_tick()\n\n        # Start the Winforms event loop.\n        WinForms.Application.Run(self.app_context)\n\n    def enqueue_tick(self):\n        # Queue a call to tick in 5ms.\n        self.task = Action[Task](self.tick)\n        Task.Delay(5).ContinueWith(self.task)\n\n    def tick(self, *args, **kwargs):\n        \"\"\"\n        Cause a single iteration of the event loop to run on the main GUI thread.\n        \"\"\"\n        # Post a userspace message that will trigger running an iteration\n        # of the asyncio event loop. This can't be done directly, because the\n        # tick() will be executing in a threadpool, and we need the asyncio\n        # handling to occur in the main GUI thread. However, by positing a\n        # message, it will be caught by the MessageFilter we installed on the\n        # Application thread.\n\n        if self.task:\n            self.task.Dispose()\n            del self.task\n        # The message is sent with:\n        # * HWND 0xfff (all windows),\n        # * MSG self.msg_id (a message ID in the WM_USER range)\n        # * LPARAM and WPARAM empty (no extra details needed; just tick!)\n        user32.PostMessageA(0xffff, self.msg_id, None, None)\n\n        # FIXME: Once we have a working message filter, this invoke call\n        # can be removed.\n        # If the app context has a main form, invoke run_once_recurring()\n        # on the thread associated with that form.\n        if self.app_context.MainForm:\n            action = Action(self.run_once_recurring)\n            self.app_context.MainForm.Invoke(action)\n            action.Dispose()\n            del action\n\n    def run_once_recurring(self):\n        \"\"\"\n        Run one iteration of the event loop, and enqueue the next iteration\n        (if we're not stopping).\n\n        This largely duplicates the \"finally\" behavior of the default Proactor\n        run_forever implementation.\n        \"\"\"\n        # Perform one tick of the event loop.\n        self._run_once()\n\n        if self._stopping:\n            # If we're stopping, we can do the \"finally\" handling from\n            # the BaseEventLoop run_forever().\n            # === START BaseEventLoop.run_forever() finally handling ===\n            self._stopping = False\n            self._thread_id = None\n            events._set_running_loop(None)\n            self._set_coroutine_origin_tracking(False)\n            try:\n                sys.set_asyncgen_hooks(*self._old_agen_hooks)\n            except AttributeError:\n                # Python < 3.6 didn't have set_asyncgen_hooks.\n                # No action required for those versions.\n                pass\n            # === END BaseEventLoop.run_forever() finally handling ===\n        else:\n            # Otherwise, live to tick another day. Enqueue the next tick,\n            # and make sure there will be *something* to be processed.\n            # If you don't ensure there is at least one message on the\n            # queue, the select() call will block, locking the app.\n            self.enqueue_tick()\n            self.call_soon(self._loop_self_reading)\n\n\n# Python 3.7 changed the name of an internal wrapper function.\n# Install an alias for the old name at the new name.\nif sys.version_info < (3, 7):\n    WinformsProactorEventLoop._set_coroutine_origin_tracking = WinformsProactorEventLoop._set_coroutine_wrapper\n", "path": "src/winforms/toga_winforms/libs/proactor.py"}], "after_files": [{"content": "import asyncio\nimport sys\nimport threading\nfrom asyncio import events\n\nfrom .winforms import Action, Task, WinForms, user32\n\n\nclass AsyncIOTickMessageFilter(WinForms.IMessageFilter):\n    \"\"\"\n    A Winforms message filter that will catch the request to tick the Asyncio\n    event loop.\n    \"\"\"\n    __namespace__ = 'System.Windows.Forms'\n\n    def __init__(self, loop, msg_id):\n        self.loop = loop\n        self.msg_id = msg_id\n\n    def PreFilterMessage(self, message):\n        print('ping', message)\n        if message.Msg == self.msg_id:\n            print(\"asyncio tick message!!\")\n            self.loop.run_once_recurring()\n            return True\n        # print(\"Filter message\", message)\n        return False\n\n\nclass WinformsProactorEventLoop(asyncio.ProactorEventLoop):\n    def run_forever(self, app_context):\n        \"\"\"Set up the asyncio event loop, integrate it with the Winforms\n        event loop, and start the application.\n\n        This largely duplicates the setup behavior of the default Proactor\n        run_forever implementation.\n\n        :param app_context: The WinForms.ApplicationContext instance\n            controlling the lifecycle of the app.\n        \"\"\"\n        # Python 3.8 added an implementation of run_forever() in\n        # ProactorEventLoop. The only part that actually matters is the\n        # refactoring that moved the initial call to stage _loop_self_reading;\n        # it now needs to be created as part of run_forever; otherwise the\n        # event loop locks up, because there won't be anything for the\n        # select call to process.\n        if sys.version_info >= (3, 8):\n            self.call_soon(self._loop_self_reading)\n\n        # Remember the application context.\n        self.app_context = app_context\n\n        # Register a custom user window message.\n        self.msg_id = user32.RegisterWindowMessageA(\"Python asyncio tick\")\n        # Add a message filter to listen for the asyncio tick message\n        # FIXME: Actually install the message filter.\n        # msg_filter = AsyncIOTickMessageFilter(self, self.msg_id)\n        # WinForms.Application.AddMessageFilter(msg_filter)\n\n        # Setup the Proactor.\n        # The code between the following markers should be exactly the same as\n        # the official CPython implementation, up to the start of the\n        # `while True:` part of run_forever() (see BaseEventLoop.run_forever()\n        # in Lib/ascynio/base_events.py)\n        # === START BaseEventLoop.run_forever() setup ===\n        self._check_closed()\n        if self.is_running():\n            raise RuntimeError('This event loop is already running')\n        if events._get_running_loop() is not None:\n            raise RuntimeError(\n                'Cannot run the event loop while another loop is running')\n        self._set_coroutine_origin_tracking(self._debug)\n        self._thread_id = threading.get_ident()\n        try:\n            self._old_agen_hooks = sys.get_asyncgen_hooks()\n            sys.set_asyncgen_hooks(\n                firstiter=self._asyncgen_firstiter_hook,\n                finalizer=self._asyncgen_finalizer_hook\n            )\n        except AttributeError:\n            # Python < 3.6 didn't have sys.get_asyncgen_hooks();\n            # No action required for those versions.\n            pass\n\n        events._set_running_loop(self)\n        # === END BaseEventLoop.run_forever() setup ===\n\n        # Rather than going into a `while True:` loop, we're going to use the\n        # Winforms event loop to queue a tick() message that will cause a\n        # single iteration of the asyncio event loop to be executed. Each time\n        # we do this, we queue *another* tick() message in 5ms time. In this\n        # way, we'll get a continuous stream of tick() calls, without blocking\n        # the Winforms event loop.\n\n        # Queue the first asyncio tick.\n        self.enqueue_tick()\n\n        # Start the Winforms event loop.\n        WinForms.Application.Run(self.app_context)\n\n    def enqueue_tick(self):\n        # Queue a call to tick in 5ms.\n        self.task = Action[Task](self.tick)\n        Task.Delay(5).ContinueWith(self.task)\n\n    def tick(self, *args, **kwargs):\n        \"\"\"\n        Cause a single iteration of the event loop to run on the main GUI thread.\n        \"\"\"\n        # Post a userspace message that will trigger running an iteration\n        # of the asyncio event loop. This can't be done directly, because the\n        # tick() will be executing in a threadpool, and we need the asyncio\n        # handling to occur in the main GUI thread. However, by positing a\n        # message, it will be caught by the MessageFilter we installed on the\n        # Application thread.\n\n        # The message is sent with:\n        # * HWND 0xfff (all windows),\n        # * MSG self.msg_id (a message ID in the WM_USER range)\n        # * LPARAM and WPARAM empty (no extra details needed; just tick!)\n        user32.PostMessageA(0xffff, self.msg_id, None, None)\n\n        # FIXME: Once we have a working message filter, this invoke call\n        # can be removed.\n        # If the app context has a main form, invoke run_once_recurring()\n        # on the thread associated with that form.\n        if self.app_context.MainForm:\n            action = Action(self.run_once_recurring)\n            self.app_context.MainForm.Invoke(action)\n\n    def run_once_recurring(self):\n        \"\"\"\n        Run one iteration of the event loop, and enqueue the next iteration\n        (if we're not stopping).\n\n        This largely duplicates the \"finally\" behavior of the default Proactor\n        run_forever implementation.\n        \"\"\"\n        # Perform one tick of the event loop.\n        self._run_once()\n\n        if self._stopping:\n            # If we're stopping, we can do the \"finally\" handling from\n            # the BaseEventLoop run_forever().\n            # === START BaseEventLoop.run_forever() finally handling ===\n            self._stopping = False\n            self._thread_id = None\n            events._set_running_loop(None)\n            self._set_coroutine_origin_tracking(False)\n            try:\n                sys.set_asyncgen_hooks(*self._old_agen_hooks)\n            except AttributeError:\n                # Python < 3.6 didn't have set_asyncgen_hooks.\n                # No action required for those versions.\n                pass\n            # === END BaseEventLoop.run_forever() finally handling ===\n        else:\n            # Otherwise, live to tick another day. Enqueue the next tick,\n            # and make sure there will be *something* to be processed.\n            # If you don't ensure there is at least one message on the\n            # queue, the select() call will block, locking the app.\n            self.enqueue_tick()\n            self.call_soon(self._loop_self_reading)\n\n\n# Python 3.7 changed the name of an internal wrapper function.\n# Install an alias for the old name at the new name.\nif sys.version_info < (3, 7):\n    WinformsProactorEventLoop._set_coroutine_origin_tracking = WinformsProactorEventLoop._set_coroutine_wrapper\n", "path": "src/winforms/toga_winforms/libs/proactor.py"}]}