0
votes

I'm trying to create a program which has Main class (which has Permanently counting method and Permanently emitting signal Received from Worker class method) and Worker class (which is counting number and emitting to Main class Permanently)

I'm new to programming So I don't know asynchronous or parallel program But I have to use signal/slot That's why I decided using pyqt

When I used QThread It was blocking main_cnt()

class Worker(QThread):
    tr_pass = pyqtSignal(int)

    def __init__(self):
        super().__init__()

    def run(self):
        cnt = 0
        while True:
            cnt += 1
            print("Worker cnt : ", cnt)
            self.tr_pass.emit(cnt)
            time.sleep(2)

class Main:
    def __init__(self):
        self.worker = Worker()
        self.worker.tr_pass.connect(self.worker_connect)
        self.worker.run()

        self.main_cnt()

    def main_cnt(self):
        cnt = 0
        while True:
            cnt += 1
            print("main cnt : ", cnt)
            time.sleep(3)

    def worker_connect(self, df):
        print("Connected by Worker : ", df)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = Main()
    app.exec_()

So I used moveToThread It works asynchronously But It doesn't work well

Terminal indicates like this and 'self.worker_.tr_pass.connect(self.worker_connect)' doesn't work

  1. main cnt : 1
  2. Worker cnt : 1
  3. Worker cnt : 1
  4. Worker cnt : 2
  5. main cnt : 2
  6. Worker cnt : 3
  7. Worker cnt : 4main cnt : 3
  8. Worker cnt : 5
  9. main cnt : 4
  10. main cnt : 4
  11. Worker cnt : 6
class Worker_(QObject):
    tr_pass = pyqtSignal(int)

    def __init__(self):
        super().__init__()

    def run(self):
        cnt = 0
        while True:
            cnt += 1
            print("Worker cnt : ", cnt)
            self.tr_pass.emit(cnt)
            time.sleep(2)
class Main:
    def __init__(self):
        self.worker_ = Worker_()
        self.thread = QThread()
        self.worker_.moveToThread(self.thread)
        self.thread.started.connect(self.worker_.run)
        self.worker_.tr_pass.connect(self.worker_connect)
        self.thread.start()

        self.main_cnt()

    def main_cnt(self):
        cnt = 0
        while True:
            cnt += 1
            print("main cnt : ", cnt)
            time.sleep(3)

    def worker_connect(self, df):
        print("Connected by Worker : ", df)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = Main()
    app.exec_()

How can I solve this problem I appreciate your answer

1

1 Answers

0
votes

If you need to run both functions at the same time then i have an answer by using QThreadpool and QRunnable.

First we create QThreadpool and call to thread running function

class Main:
def __init__(self):
    self.threadpool = QThreadPool()
    self.run_function_in_thread(self.main_cnt)

Then add function which will start every function in a thread

def run_function_in_thread(self,function):
    worker = Worker(fn=function)
    self.threadpool.start(worker)

By creating Worker

class Worker(QRunnable):

    def __init__(self,fn):
        super().__init__()
        self.fn = fn

    def run(self):
        self.fn()

Then I added new function based on the logic from your Worker class

def another_cnter(self):
    cnt = 0
    while True:
        cnt += 1
        print("Worker cnt : ", cnt)
        self.worker_connect(cnt)
        time.sleep(2)

Full code:

class Worker(QRunnable):

    def __init__(self,fn):
        super().__init__()
        self.fn = fn

    def run(self):
        self.fn()

class Main:
    def __init__(self):
        self.threadpool = QThreadPool()
        self.run_function_in_thread(self.another_cnter)
        time.sleep(0.5)
        self.run_function_in_thread(self.another_cnter)
        time.sleep(0.5)
        self.run_function_in_thread(self.main_cnt)

    def run_function_in_thread(self,function):
        worker = Worker(fn=function)
        self.threadpool.start(worker)

    def main_cnt(self):
        cnt = 0
        while True:
            cnt += 1
            print("main cnt : ", cnt)
            time.sleep(3)

    def another_cnter(self):
        cnt = 0
        while True:
            cnt += 1
            print("Worker cnt : ", cnt)
            self.worker_connect(cnt)
            time.sleep(2)

    def worker_connect(self,df):
        print("Connected by Worker : ", df)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    main = Main()
    app.exec_()

Extra
There are different ways to add signals and slots. One way would be:
Make a new class:

class WorkerSignals(QObject):
    counter = pyqtSignal(int)

Initialize and pass to function

class Worker(QRunnable):
    def __init__(self,fn):
        super().__init__()
        self.signals = WorkerSignals()
    def run(self):
        self.fn(self.signals)

Connect to function

def run_function_in_thread(self,function):
    worker = Worker(fn=function)
    worker.signals.counter.connect(self.print_out_line)
    self.threadpool.start(worker)

And then emit signal in functions

def main_cnt(self,signals):
    cnt = 0
    signals.counter.emit(cnt)