質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

2492閲覧

Threading実行中に他のThreadを呼び出すのは不可能?

tomo1998

総合スコア34

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2018/12/20 05:42

編集2018/12/20 06:00

前提・実現したいこと

今作成しているプログラムでThreadが別のThreadを呼び出すコードを書いたのですがエラーが起こってしまいます。

該当のソースコード

分かりやすいようにちょっと簡単なプログラムを用意しました
以下のプログラムを実行すると画面が形成されて、そこに0,Start,Stopというボタンが表示されます。
Startというボタンを押したら数字がカウントされて0の部分が更新され、Stopを押すとカウントが止まります。

python

1import tkinter as tk 2import threading 3 4class App(object): 5 def __init__(self): 6 self.frame=1 7 self.stop_fg=False 8 9 self.gui() 10 11 def gui(self): 12 self.root=tk.Tk() 13 self.Label001=tk.Label(self.root,text="0") 14 self.Label001.pack() 15 Button001=tk.Button(self.root,text="Start",command=self.on_start) 16 Button001.pack() 17 Button002=tk.Button(self.root,text="Stop",command=self.on_stop) 18 Button002.pack() 19 self.root.mainloop() 20 21 def on_start(self): 22 threading.Thread(target=self.on_run).start() 23 24 def on_stop(self): 25 self.stop_fg=True 26 27 def on_run(self): 28 self.stop_fg=False 29 30 while self.stop_fg!=True: 31 #threading.Thread(target=self.count).start() 32 33 #上のコードを実行する場合、下の2つのコードをコメント化する必要があります 34 self.Label001["text"]=self.frame 35 self.frame=self.frame+1 36 37 def count(self): 38 self.Label001["text"]=self.frame 39 self.frame=self.frame+1 40 41app=App() 42

発生している問題・エラーメッセージ

カウントを担当している部分をthreadで処理させたいのですが、コメント化している文を実行させた場合、Startボタンを押すとプログラムがフリーズしてしまいます。

Thread内から他のThreadを呼び出しているのが原因なんでしょうが、なんとかしてエラーを回避することはできないでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

count関数は内部に処理ループを持っていないので、スレッド関数にする意味合いがありません。また、ループ内で毎回スレッド生成する必要もありません。

時間のかかる処理をさせつつボタンを反応させるには、単純に以下でよいです。

Python

1 # 略 2 def on_run(self): 3 self.stop_fg=False 4 while self.stop_fg!=True: 5 #threading.Thread(target=self.count).start() # 毎ループスレッドを生成している! 6 self.count() 7 8 def count(self): 9 self.Label001["text"]=self.frame 10 self.frame=self.frame+1 11 time.sleep(1) # 時間のかかる処理

なお、スレッドを用いても、もともと時間のかかる直列的に行っている処理(画像撮影→解析→保存など)を短縮することは原理的にできません。

投稿2018/12/20 06:26

編集2018/12/20 07:16
can110

総合スコア38266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tomo1998

2018/12/20 06:53

回答ありがとうございます。 確かに普通ならそれでもいいのですが、しかし1つ問題がありまして。 今作ろうとしているプログラムはカメラに映るものを静止画として連続で撮る、といったコードなのですが、上記のコードの countに相当するメソッドで写真を撮影および保存しているんです。 それで、撮影と保存にはどうしてもかなり処理時間がかかってしまい、単純なプログラムだと写真を撮る速度がかなり下がるんです そこで、Threadingによる別処理を利用することでこの問題を解決できると思うんです。 なので出来ればこの方法でコードを書きたいんです。 説明不足ですいません m(_ _)m
can110

2018/12/20 07:19

回答に追記しましたが、スレッドを用いても直列でおこなうべき処理は短縮することはできません。 スレッドで短縮できる処理とは、Webから複数ファイルをダウンロードするなど、同時並行的に処理できるものです。
tomo1998

2018/12/20 07:30

ふむ・・・ 本処理側は解析する数だけ別スレッドを呼び出し、別スレッドで保存処理をやらせることで メソッドの処理速度には関係なく、結果的に撮影枚数を増やすことができると思ったのですが、それでも短縮は不可なのですか?
can110

2018/12/20 07:39 編集

解析と保存が同時並行できる処理であれば、別スレッドにすることにより短縮できる可能性はあります。 しかし仮に解析はあまり時間がかからない処理で、保存が実ファイルシステムに対してであれば、最終的には同時に1つしか書き込みできないので、スレッド化するメリットはほぼない(保存がボトルネックになる)と思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問