Multithreading PyQt applications with QThreadPool


#41

hey Martin ,thanks for your informative article,have learned quite a lot from it ,I m a complete newbie to pyqt
especially the qthreadpools class,I am trying to implement it to display quite a large number of videos files co-currently( 20 vids ) and in real time ,the worker threads does their job pretty well i bet,my only draw back is their speed,can you help please


#42

Thanks :slight_smile:

There’s no direct way to stop a running thread from the outside (you can’t send a “shutdown” signal to the runner). But you can use the signals/slots system to send a kill notification into your code — if you detect this you can exit gracefully (or not so much).

This is fine if the steps in what you doing are small enough, e.g. taking 2-5 seconds a step. But if you’ve got some long-running request for example the kill will take as long as it takes.

One of the nice things about the QThreadPool approach though is that you can just tell the task to die and forget about it.


#43

Hey man, I haven’t got much experience with video processing (anyone else?) but what are you trying to do in the threads specifically? The decoding?

The signal-slot mechanism would definitely be too slow for sending out video data, but then again you shouldn’t have to — there are built in GUI components for video streaming in Qt, which can handle all that in another thread for you.

I put together a small demo app for Qt multimedia here: https://www.pymadethis.com/article/media-player-python-qt/ — it’s just a single window, but shows you how it’s done.


#44

That was SO helpful and well explained !
THANKS !

However I’m not quite understanding how progress_callback is passed between the classes.

When initialising Worker, only the function execute_this_fn is passed.
Then in the execute_this_fn function, we provide progress_callback which is not declared (to my eyes this should provide an error since no argument is passed to the function… but it works so I’m missing something).

Also how does execute_this_fn knows that it’s the progress_callback kwarg declared in Worker.

Rha !

Edit : my brain melted but it’s ok now.
So the answer is :
Since the execute_this_fn is called from run inside the class Worker, and that self.kwargs is passed, the progress_callback being passed at the init of the class, indeed the keyword will always been present. yay :slight_smile:


#45

You got it! :slight_smile:

I’m not particularly fond of that code for that reason — it is technically correct, but it’s none-obvious. On the upside it’s better than it was… I used to have it assigning to kwargs rather than self.kwargs. They’re the same object so it doesn’t matter, but then you’re assigning after storing, which is even more “uh?”

Can you see a way to make this clearer?


#46

Yes ! I got it !
Tbh I’m probably confused because I’m fairly new to using class with Python (15 days).
So I’m still learning what can be done. This was quite surprising but makes sense !
The explanation is quite clear now : We do provide only the function object. When the function is called we do provide the needed arguments that are stored in self.kwargs. :slight_smile: