Am Montag, 30. September 2019 11:46:43 UTC+2 schrieb Barry Scott: > > On 29 Sep 2019, at 21:41, Eko palypse <ekopaly...@gmail.com> wrote: > > > > Am Sonntag, 29. September 2019 19:18:32 UTC+2 schrieb Barry Scott: > >>> On 29 Sep 2019, at 14:14, Eko palypse <ekopaly...@gmail.com> wrote: > >>> > >>> Unfortunately, I can't make all callbacks synchronous or asynchronous > >>> because this has negative effects on the application in one way or > >>> another. > >> > >> Surely you can make all callbacks async? > >> You do not have to have them wait, they can complete their work in one > >> call. > >> > >> sync == async-that-does-not-await > >> > >> Barry > > > > Thank you for your answer but I'm sorry I don't get it. > > What do you mean by I don't have to have them wait? > > > > Let me explain my understanding, with some pseudo code, how async callbacks > > works and please keep in mind that I'm a novice when it comes to OO designs > > and basic software design strategies/techniques, so I might be totally > > wrong about what I'm doing. > > When you said async I thought you meant the specific programming model in > Python > that uses "async def", "await" etc. You are using threads. > > The problem you are facing is that the UI must not become unresponsive. > Further a background thread cannot call any UI framework functions as the UI > framework can only be called on the main thread. > > You can run fast event handers on the UI thread but slow running handlers > must be run on another thread to allow the UI to be responsive. > > What I do is have the event handler for a long running task take the > responsibility > to queue the task onto a background thread. While the task is running it > sends status > to the UI thread so that UI elements are updated (progress bars, etc). > > If you are using PyQt5 you might find the code I used for SCM Workbench > interesting. > > I can write event handlers that look like this: > > @thread_switcher > def eventHandler( self, ... ): > # starts in the foreground (UI thread) > self.status.update('Working...') > > yield self.switchToBackground > # now on the background thread > self.doSlowTask() > > yield self.switchToForeground > # now in the foreground > self.status.update('Done') > > The code is in: > > https://github.com/barry-scott/scm-workbench/blob/master/Source/Common/wb_background_thread.py > > @thread_switcher adds an attribute to the function so the rest of the > code knows this is an event handler that needs to use a background thread. > > When I add an event handler I call through a function (wrapWithThreadSwitcher) > that wraps only functions that have been marked with @thread_switcher. > > The rest of the code is the machinery to handle moving between threads via > the generator. > > Barry > > > > > An SYNCHRONOUS callback is like this. Event/notification gets fired and > > notification handler calls all registered methods one after the other. > > Something like > > > > if notification.list_of_methods: > > for method in list_of_methods: > > method() > > > > whereas an ASYNCHRONOUS callback is more like this. Event/notification gets > > fired and notification handler informs another thread that the event has > > been fired and all registered async callback methods should get executed. > > So something like this > > > > class EventThread(threading.Thread): > > def __init__(...): > > super()... > > self.event = threading.Event() > > self.kill = False > > ... > > def run(self): > > while True: > > self.event.wait() > > self.event.clear() > > if not self.kill: > > for method in self.list_of_methods: > > method() > > > > et = EventThread() > > if notification.list_of_methods: > > et.event.set() # run all async methods > > for method in list_of_methods: # run sync methods > > method()) > > > > > > So if there is no synchronous callback for that notification then the > > notification handler would just set the event and return. > > The EventThread would then call one registered callback after the other. > > Right? > > > > Using this approach does sound fine from UI point of view as there is > > minimal impact and UI keeps responsive but from code execution point of view > > it sound much more complicated. What if one async callback is slow or buggy? > > This could lead to unpredictable behavior where as in a synchronous > > execution you immediately know what is causing it. > > That was the reason I decided not to offer async callbacks until I > > discovered that other parts, like UI modifications aren't working properly. > > And there are notification which must be called in a synchronous way, like > > the modification event. If you want to intercept a modification safely then > > it can only be done within a synchronous callback. > > > > Does this makes sense to you? Or do I have wrong understanding or, again, an > > wrong assumption how this works? > > > > Thank you > > Eren > > -- > > https://mail.python.org/mailman/listinfo/python-list > >
Thank you very much, this sounds like what I'm looking for and I'm sure I find tons of other useful information/techniques which I'm not aware of yet. Thank you Eren -- https://mail.python.org/mailman/listinfo/python-list