'Reduce CPU usage in Pywin32 system tray app main loop

I built a small system tray app based on Simon Brunning's example.

According to How can I use win32gui in order to have an app run in the background?, calling win32gui.PumpMessages() runs a loop by itself, but I need to make an HTTP request every ~15 min and if necessary update the system tray icon and tooltip.

I do this by creating a separate process with an infinite loop, sleeping for 900 s after every request, which updates a dictionary shared between the two (main app, requesting) processes. The main app runs an infinite loop checking the shared dictionary for updates and win32gui.PumpWaitingMessages() on every cycle, which I would like to keep so I can get a tooltip immediately on hovering or the context menu on clicking.

This is a simplified version of the relevant part of the code, with hopefully sufficient detail to show how it works:

from multiprocessing import Process, Manager

def get_data(data):
  while True:
    new_data = make_request()
    data["value"] = new_data
    data["refresh"] = True
    sleep(900)

class SysTrayIcon():
  def __init__():
    self.data = Manager().dict({"value": "foo", "refresh": False})
    self.update_process(target=get_data, args=(self.data))
    self.update_process.start()

    while True:
      if self.data["refresh"]:
        self.refresh_icon()
        self.data["refresh"] = False
      win32gui.PumpWaitingMessages()

I see a pretty high CPU load (~10%) which is probably due to the loop running very quickly and checking self.data["refresh"] repeatedly.

What would be an elegant way to avoid this and/or reduce CPU load? I could probably just add a simple sleep(0.03) on every iteration which would still give me a sufficiently quick response for interactions with the app, but maybe there is a better solution?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source