59371
2つのスレッド処理を組み合わせてプログラムを組みたいのですが  
エラーが出てしまい、うまく行きません。

1つ目が、1秒ごとにGUIをprintを行うプログラム(threadingGUI.py)です。  
tkinterというライブラリでGUIを作っているのですが、普通にwhileループを回すとGUIがフリーズします。  
whileループを回してもGUIがフリーズしないように、threading処理をしてあります。  
(参考記事：<https://teratail.com/questions/147384>)

**threadingGUI.py**

```

    import tkinter as tk
    import threading
    import time
    
    class threadingGUI():
        def __init__(self):
            self.frame=1
            self.stop_flag=False
            self.thread=None
    
        def time_count(self):
            while not self.stop_flag:
                print(self.frame)
                self.frame=self.frame+1
                time.sleep(1)
    
        def start(self):
            if not self.thread:
                self.thread = threading.Thread(target=self.time_count)
                self.stop_flag=False
                self.thread.start()
    
        def stop(self):
            if self.thread:
                self.stop_flag=True
                self.thread.join()
                self.thread=None
    
        def GUI_start(self):
            root=tk.Tk()
            Button001=tk.Button(root,text="Start",command=self.start)
            Button001.pack()
            Button002=tk.Button(root,text="Stop",command=self.stop)
            Button002.pack()
            root.mainloop()
    
            self.stop_flag=True
            self.thread.join()
    
    t = threadingGUI()
    t.GUI_start()
    
```

2つ目が、一定周期でプログラムを実行するためのプログラムです。  
単純にsleepをするだけだと、プログラムの実行時間分のズレが発生するようなので  
sleepとthreadingを組み合わせています。  
(参考記事：<https://qiita.com/montblanc18/items/05715730d99d450fd0d3>)

**threading_and_sleep.py**

```

    import time
    import threading
    
    def worker():
        print(time.time())
        time.sleep(8)
    
    def scheduler(interval, f, wait = True):
        base_time = time.time()
        next_time = 0
        while True:
            t = threading.Thread(target = f)
            t.start()
            if wait:
                t.join()
            next_time = ((base_time - time.time()) % interval) or interval
            time.sleep(next_time)
    
    scheduler(1, worker, False)
    
```

threadingGUI.pyと、threading_and_sleep.pyを組み合わせて  
以下のように、なるべく正確に一定間隔でprintするプログラム(threading_and_sleepGUI.py)を書いてみようとしたのですが、実行すると、startボタン実行時にGUIがフリーズしてしまいます。

**threading_and_sleepGUI.py**

```

    import tkinter as tk
    import threading
    import time
    
    class threading_and_sleepGUI():
        def __init__(self):
            self.stop_flag=False
            self.thread=None
    
        def worker(self):
            print(time.time())
            time.sleep(8)
    
        def scheduler(self,interval, f, wait = True):
            base_time = time.time()
            next_time = 0
            while not self.stop_flag:
                t = threading.Thread(target = f)
                t.start()
                if wait:
                    t.join()
                next_time = ((base_time - time.time()) % interval) or interval
                time.sleep(next_time)
    
        def start(self):
            if not self.thread:
                self.thread = threading.Thread(target=self.scheduler(1, self.worker, False))
                self.stop_flag=False
                self.thread.start()
    
        def stop(self):
            if self.thread:
                self.stop_flag=True
                self.thread.join()
                self.thread=None
    
        def GUI_start(self):
            root=tk.Tk()
            Button001=tk.Button(root,text="Start",command=self.start)
            Button001.pack()
            Button002=tk.Button(root,text="Stop",command=self.stop)
            Button002.pack()
            root.mainloop()
    
            self.stop_flag=True
            self.thread.join()
    
    t = threading_and_sleepGUI()
    t.GUI_start()
    
```

スレッド処理の最中にスレッド処理が含まれていると不具合が起きてしまうのでしょうか？  
どうしたらGUIをフリーズさせず、一定間隔でprintを行うように出来ますか？
CC BY-SA 4.0
2019-09-30T14:29:28.143
59369
2019-09-30T18:15:53.900
34471
question
python
Python スレッド処理の記述の中にもう1つスレッド処理を作りたい
`self.thread = threading.Thread(target=self.scheduler(1, self.worker,
False))`でtargetの引数指定の方法が間違いです。

[class threading.Thread(group=None, target=None, name=None, args=(),
kwargs={}, *,
daemon=None)](https://docs.python.org/ja/3/library/threading.html#threading.Thread)

> args は target を呼び出すときの引数タプルです。デフォルトは () です。

正しくは、`self.thread = threading.Thread(target=self.scheduler, args=(1,
self.worker, False))`になります。
CC BY-SA 4.0
2019-09-30T18:15:53.900
59371
2019-09-30T18:15:53.900
26370
59369
answer