グラフィカルアプリケーションでマルチスレッドを使用する必要性についての適切な説明を探しています。以下の例ではPythonが使用されていますが、質問はPython固有ではなく、任意の言語でのグラフィカルプログラミングの一般的な設計に当てはまります。
簡単な例を見てみましょう。ファイルのコレクションに対してある種の時間のかかる操作を実行し、その進行状況をコンソールに出力するアプリケーションがあると仮定します。この操作にはファイルごとに2秒かかり、1.txt、2.txt、3.txt、...10.txtという名前の10個のファイルを処理するとします。次に、実装例は次のようになります。
コンソール
import time
def process(file):
print 'processing {0}...'.format(file)
time.sleep(2.0) #simulate slow operation
files = ['{0}.txt'.format(i) for i in range(1, 11)]
map(process, files)
コンソールの例はもちろんシングルスレッドであり、問題なく機能します。ここで、グラフィカルなプログレスバーを追加する場合、シングルスレッドの実装は次のようになります。
シングルスレッドのGUI
import time, gtk, gobject
def process(file):
print 'processing {0}...'.format(file)
time.sleep(2.0)
class MainWindow(gtk.Window):
def __init__(self):
super(MainWindow, self).__init__()
self.progress = gtk.ProgressBar()
self.progress.set_fraction(0)
self.add(self.progress)
self.connect("destroy", gtk.main_quit)
self.show_all()
files = ['{0}.txt'.format(i) for i in range(1, 11)]
gobject.timeout_add(100, self.submit, files, 0)
def submit(self, files, i):
process(files[i])
self.progress.set_fraction((i + 1.0)/len(files))
if i + 1 < len(files):
gobject.idle_add(self.submit, files, i + 1)
win = MainWindow()
gtk.main()
これは正常に機能しているように見えますが、たとえばウィンドウのサイズを変更してみるなど、アプリケーションを実行しようとすると、スタックし、保留中のGUIイベントを処理するために解放されたときに2秒ごとにのみ応答します。最後の例はマルチスレッドの実装であり、実行中ずっと応答性を維持します。
マルチスレッドGUI
import time, gtk, gobject, threading
def process(file):
print 'processing {0}...'.format(file)
time.sleep(2.0)
class MainWindow(gtk.Window):
def __init__(self):
super(MainWindow, self).__init__()
self.progress = gtk.ProgressBar()
self.progress.set_fraction(0)
self.add(self.progress)
self.connect("destroy", gtk.main_quit)
self.show_all()
files = ['{0}.txt'.format(i) for i in range(1, 11)]
threading.Thread(target=self.submit, args=(files,)).start()
def submit(self, files):
for i, file in enumerate(files):
process(file)
gobject.idle_add(self.progress.set_fraction, (i + 1.0)/len(files))
if not self.get_visible():
return
gtk.gdk.threads_init()
win = MainWindow()
gtk.main()
コードに長時間実行されるブロッキング操作があり、マルチスレッドソリューションを使用する必要があるレスポンシブGUIが必要な場合は、完全に明確で論理的に思えます。それを回避する他の方法はありません。これは本当ですか?私はこれを他の開発者に何度も説明しようとしましたが、多くの人は理解していないか、同意していません。誰かがこの概念の説明、それに関する記事へのリンクを提供することができますか、または私の理解が間違っている場合は私を訂正できますか?