在不滞后于主进程的情况下线程更新单独的进程

Threading to update separate process while not lagging main process

抱歉,如果这很简单,我只是不知道我做错了什么。

我需要从我每 10 秒抓取一次的网站更新信息(以免网站超载)。我想使用 pygame 显示来自网站的信息。我试过使用线程模块。但是,当我让线程休眠时,它会休眠整个程序。

例如,当我做类似的事情时:

def func():
    print('Hello1')
    time.sleep(4)
    print('Hello2')

class Display():

    def __init__(self):

        pg.init()

        self.win = pg.display.set_mode((WIN_WIDTH,WIN_HEIGHT))
        pg.display.set_caption(WIN_TITLE)
    def thread_function(self):
        x = threading.Thread(target = func)
        x.start()

    def initialize_display(self):
        run = True
    while run:
        self.win.fill(WHITE)
        self.thread_function()
        for event in pg.event.get():

            if event.type == pg.QUIT:
                run = False
                #deactivate pg library
                pg.quit()
                #quit program
                quit()
        pg.display.update()

if __name__ == "__main__":
    display = Display()
    display.initialize_display()

整个程序等待4.如何才能让func()的进程在4秒后才执行?

您确定要每帧开始一个新线程吗?也许只创建一次线程并在线程的目标函数内启动另一个循环,或者用另一个也能正常处理退出线程的函数包装该函数。

你可以这样做:

import pygame as pg
import threading
import time
import signal
WIN_WIDTH,WIN_HEIGHT=(400,400)
WIN_TITLE=''
WHITE='white'

def func():
    print('Hello1')
    time.sleep(4)
    print('Hello2')

class Display():

    def __init__(self):
        pg.init()
        self.win = pg.display.set_mode((WIN_WIDTH,WIN_HEIGHT))
        pg.display.set_caption(WIN_TITLE)
    
    def thread_function(self, should_stop):
        print('[Display] starting thread')
        
        # 'func' is wrapped in this wrapper function
        # the wrapper loops until the 'should_stop'-callback returns true
        def wrapper(should_stop):
            print('start doing something')
            while not should_stop():
                func()
            print('stop doing something')
            
        x = threading.Thread(target = wrapper, args = [should_stop])
        x.start()
        return x
        
    def initialize_display(self):
        # run could also be an attribute of Display ....
        run = True

        # we keep a reference of the thread to we can wait
        # for it to finish once we told it to stop
        thread = self.thread_function(lambda: not run)

        # when the process should be killed (e.g. CTRL+C), we also want
        # to stop the thead by setting 'run' to false
        def stop(sig, frame):
            print('[Display] got killed, stop thread')
            nonlocal run 
            run = False
        
        signal.signal(signal.SIGINT, stop)

        # just a little moving Rect so we see the main loops works
        # fine while the thread runs in the background
        r = pg.Rect((0, 200, 20, 20))
        d = 1
        clock = pg.time.Clock()
        while run:
            self.win.fill(WHITE)
            
            for event in pg.event.get():
                if event.type == pg.QUIT:
                    # setting 'run' to false will also stop the loop
                    # of the wrapper function
                    run = False
                    print('[Display] waiting for thread to finish')
                    # let's wait for the thread to finish
                    thread.join()
                    return
                    
            pg.draw.rect(self.win, 'dodgerblue', r)
            r.move_ip(d, 0)
            if not self.win.get_rect().contains(r):
                d *= -1
            pg.display.update()
            clock.tick(60)
            
if __name__ == "__main__":
    display = Display()
    display.initialize_display()