Skip to content

Commit

Permalink
Long-running tasks in background thread
Browse files Browse the repository at this point in the history
Signed-off-by: Damien Jeandemange <[email protected]>
  • Loading branch information
jeandemanged committed Nov 20, 2024
1 parent b78b5a8 commit c4be200
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 14 deletions.
37 changes: 36 additions & 1 deletion yagat/app_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
# SPDX-License-Identifier: MPL-2.0
#
import logging
import threading
import tkinter as tk
from typing import Callable, Optional

import pypowsybl.network as pn
import pypowsybl.loadflow as lf
import pypowsybl.network as pn

import yagat.networkstructure as ns

Expand All @@ -33,6 +34,8 @@ def __init__(self, root: tk.Tk):
self.tab_group_changed_listeners: list[Callable[[str], None]] = []
self.tab_changed_listeners: list[Callable[[str], None]] = []
self.view_changed_listeners: list[Callable[[str], None]] = []
self._long_running_task: Optional[threading.Thread] = None
self._network_changed_listener_enabled: bool = True

@property
def tk_root(self) -> tk.Tk:
Expand Down Expand Up @@ -121,6 +124,8 @@ def add_network_changed_listener(self, listener: Callable[[Optional[pn.Network]]
self.network_changed_listeners.append(listener)

def notify_network_changed(self) -> None:
if not self.network_changed_listener_enabled:
return
for listener in self.network_changed_listeners:
listener(self.network)

Expand Down Expand Up @@ -153,3 +158,33 @@ def add_view_changed_listener(self, listener: Callable[[str], None]) -> None:
def notify_view_changed(self) -> None:
for listener in self.view_changed_listeners:
listener(self.selected_view)

@property
def network_changed_listener_enabled(self) -> bool:
return self._network_changed_listener_enabled

@network_changed_listener_enabled.setter
def network_changed_listener_enabled(self, value: bool) -> None:
self._network_changed_listener_enabled = value

def start_long_running_task(self, name: str, target, args=(), on_done=None):
if self._long_running_task is not None:
self.status_text = 'Another task is already running, try again later'
return
self._long_running_task = threading.Thread(None, target, name, args)
logging.info(f'Task {self._long_running_task.name} starting')
self._long_running_task.start()

def schedule_check():
self._root.after(200, check_if_done)

def check_if_done():
if not self._long_running_task.is_alive():
logging.info(f'Task {self._long_running_task.name} completed')
self._long_running_task = None
if on_done is not None:
on_done()
else:
schedule_check()

schedule_check()
26 changes: 21 additions & 5 deletions yagat/menus/impl/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,18 @@ def open_network(self):
self.context.status_text = 'File opening cancelled by user'
else:
self.context.status_text = 'Opening ' + filename
self.context.network = pp.network.load(filename)
self.context.status_text = f'Network {self.context.network.name} loaded'
# disable the network changed listener, the tree view update is messed up in GUI if updated in thread
self.context.network_changed_listener_enabled = False

def task():
self.context.network = pp.network.load(filename)

def on_done():
self.context.status_text = f'Network {self.context.network.name} loaded'
self.context.network_changed_listener_enabled = True
self.context.notify_network_changed()

self.context.start_long_running_task(name='Opening file', target=task, on_done=on_done)

def save_network(self):
if not self.context.network:
Expand All @@ -99,6 +109,12 @@ def save_network(self):
if not filename:
self.context.status_text = 'File save cancelled by user'
else:
self.context.status_text = 'Saving ' + filename
self.context.network.save(filename)
self.context.status_text = f'Network {self.context.network.name} saved to {filename}'
self.context.status_text = f'Saving {filename}'

def on_done():
self.context.status_text = f'Network {self.context.network.name} saved to {filename}'

def task():
self.context.network.save(filename)

self.context.start_long_running_task(name='Saving file', target=task, on_done=on_done)
26 changes: 18 additions & 8 deletions yagat/menus/impl/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,24 @@ def __init__(self, parent, context: AppContext, *args, **kwargs):
self.parent = parent
self.context = context
parent.add_cascade(label="Run", menu=self)
self.add_command(label='Load Flow', command=self.run_load_flow)
self.add_command(label='AC Load Flow', command=lambda: self.run_load_flow(ac=True))
self.add_command(label='DC Load Flow', command=lambda: self.run_load_flow(ac=False))

def run_load_flow(self):
def run_load_flow(self, ac: bool):
reporter = pr.Reporter()
self.context.status_text = 'Starting Load Flow'
results = lf.run_ac(self.context.network, parameters=self.context.lf_parameters, reporter=reporter)
self.context.status_text = 'Load Flow completed'
self.context.network_structure.refresh()
self.context.notify_selection_changed() # hack to trigger refresh
print(results)
print(reporter)

def on_done():
self.context.network_structure.refresh()
self.context.notify_selection_changed() # hack to trigger refresh
self.context.status_text = 'Load Flow completed'

def task():
if ac:
results = lf.run_ac(self.context.network, parameters=self.context.lf_parameters, reporter=reporter)
else:
results = lf.run_dc(self.context.network, parameters=self.context.lf_parameters, reporter=reporter)
print(results)
print(reporter)

self.context.start_long_running_task(name='Load Flow', target=task, on_done=on_done)

0 comments on commit c4be200

Please sign in to comment.