Python Forum
Sending a custom signal from a worker - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Sending a custom signal from a worker (/thread-10834.html)



Sending a custom signal from a worker - mhc - Jun-08-2018

Hi all, I'm working in a Python application, using PySide on a Raspberry Pi, with Raspbian Jessie OS.

I'm very new in Python, so I'm not an expert at all, and probably it's a begginer's question.

In my application, I have:

main thread -> Gui Thread that implements front end.
subyacent thread -> Makes some long work (no gui at all, plain code), implemented in a Custom class named MyWorker.

In some places of subyacent thread's code, I need to emit a signal that have to be catched by the main thread. In a previous version, I did it this way:

Main thread's code

    #Slot for clicked button
    def Slot_Start_Calculation (self):

        self.MyLongThread = QThread()
        MyLongWorker = MyWorker(self, Qty)
        MyLongWorker.moveToThread(self.MyLongThread)

        self.MyLongThread.started.connect(MyLongWorker.Run_LongWorker)
        MyLongWorker.WorkerFinished.connect(self.MyLongThread.quit)
        MyLongWorker.WorkerFinished.connect(self.MyLongWorker.deleteLater)
        MyLongThread.finished.connect(self.MyLongThread.deleteLater)

        MyLongThread.start()


    def Slot_Worker_Sent_A_Signal (self, Result):

        print ("Worker sent this result: " + str(Result))
        .
        .
        .
MyWorker's code

    class MyWorker(QObject):

    WorkerFinished = Signal()
    CustomSignal = Signal(int)

    def __init__(self, parent, Quantity)

        super().__init__(parent)
        self_parent = parent
        self.Quantity = Quantity
        print("Myworker's constructor")

    def __del__(self):
        print("Myworker's destructor")


    def Run_LongWorker (self):

        self.CustomSignal.connect(self.parent.Slot_Worker_Sent_A_Signal)
        .
        .
        .
        self.CustomSignal.emit(MyPartialResult)
        .
        .
        .
        self.WorkerFinished.emit()
This code is running in a test environment from some weeks ago while I finish some details of the GUI, and I didn't see anything wrong. Yesterday searching in the web I casually noticed that QObject::moveToThread can't move objects with a parent

[1]]https:[//forum.qt.io/topic/40653/qobject-movetothread-cannot-move-objects-with-a-parent][1]

so I'm afraid that my code may have problems that I have not yet detected.

I modified this part of code, and now it is:

New code for main Thread
    #New slot for clicked button.
    def Slot_Start_Calculation (self):

        MyLongThread = QThread()
        MyLongWorker = MyWorker(Qty)
        MyLongWorker.moveToThread(MyLongThread)

        MyLongThread.started.connect(MyLongWorker.Run_LongWorker)
        MyLongWorker.WorkerFinished.connect(MyLongThread.quit)
        MyLongWorker.WorkerFinished.connect(MyLongWorker.deleteLater)
        MyLongThread.finished.connect(MyLongThread.deleteLater)

        MyLongThread.start()


    def Slot_Worker_Sent_A_Signal (self, Result):

        print ("Worker sent this result: " + str(Result))
        .
        .
        .
New code for MyWorker

class MyWorker(QObject):

    WorkerFinished = Signal()
    CustomSignal = Signal(int)

    def __init__(self, Quantity)

        super().__init__()
        self.Quantity = Quantity
        print("Myworker's constructor")

    def __del__(self):
        print("Myworker's destructor")

    def Run_LongWorker (self):

        self.CustomSignal.connect( ??? .Slot_Worker_Sends_A_Signal)
        .
        .
        .
        self.CustomSignal.emit(MyPartialResult)
        .
        .
        .
        self.WorkerFinished.emit()
So, now, I don't really know how to connect this signal to a slot that lives in main thread, cause if I'm not wrong, there is no parent/children relation since I changed thread affinity.

Could someone please tell me if there is a way to do this, and guide me towards documentation about this problem?

Many thanks in advance.


RE: Sending a custom signal from a worker - Larz60+ - Jun-08-2018

Here's something to read: http://greenteapress.com/semaphores/LittleBookOfSemaphores.pdf


RE: Sending a custom signal from a worker - mhc - Jun-08-2018

Thank you very much Larz60+. I will read it, and I will publish my solution if I can find it.

Regards


RE: Sending a custom signal from a worker - mhc - Jun-25-2018

Hi again.

I read the document that Larz60+ recommended (very good and interesting), but I still can't see how to deal with a solution to my specific problem.

Thing that misleads me is how can I use a semaphore in my main thread (if this is the resource that Larz60+ suggested me) beacuse main thread is a GUI with an event loop in which, if I wait for a signal from the Worker, I´m leaving hung all functions of the front end.

Sorry cause trying to be simple I was very inespecific with the function of the worker. I think that the important thing to take in account is that this worker makes a job than can be running for many minutes, then has to inform a partial result to main thread and keep running for a while.

Could someone please tell me if I'm wrong, or guide me in the right direction?

Many thanks in advance!


RE: Sending a custom signal from a worker - mhc - Jul-03-2018

Finally, I think I found an answer. In constructor of the Worker class, I had to change the parent object reference and the super class init calling.

class MyWorker(QObject):
 
WorkerFinished = Signal()
CustomSignal = Signal(int)
 
def __init__(self, parent = None, Quantity)
 
    super().__init__()
    self.Quantity = Quantity
    print("Myworker's constructor")
 
def __del__(self):
    print("Myworker's destructor")
 
 
def Run_LongWorker (self):
 
    self.CustomSignal.connect(self.parent.Slot_Worker_Sent_A_Signal)
    .
    .
    .
    self.CustomSignal.emit(MyPartialResult)
    .
    .
    .
    self.WorkerFinished.emit()
And now everything is working as expected.

If somebody sees a problem with that code, please feel free to tell me.

Thanks!