私は長い実行中のバックグラウンド(デーモン)プロセスとwxベースのUIを持つアプリを持っています。バックグラウンドプロセスは、実行中にデーモンプロセスのステータス更新を取得するために、UIが読み取るべきマルチプロセッシング.JoinableQueue()にメッセージを置きます。私が抱えている問題は、AwaitStatusReportThreadClassインスタンスがUIにメッセージを渡している間にUIが応答を停止することです。下のコードを実行し、ウィンドウのサイズを変更しようとすると、アプリケーションは応答していないと表示します。私はPython27 32ビットを使用して、Windows 7上でこれを実行しているwx Phoenix UIを更新するために、スレッドが結合可能なキューメッセージに応答するようにするにはどうすればよいですか?
、wxPythonのの4.0.0a3(フェニックス)
私のアプリは、様々なPythonのファイルで構成されているが、私は以下のコードでエラーを再現することができました。それはかなり簡単です。私はAwaitStatusReportThreadClassというクラスを作成して、hereのpub/subメソッドを使ってUIを更新しました。このクラスのinitメソッドには、ステータスメッセージをチェックする無限ループがあります。あるものが見つかると、StatusBarメッセージが更新されます。
import multiprocessing
import threading
import wx
import sys
from wx.lib.pubsub import pub
class AwaitStatusReportThreadClass(threading.Thread):
"""This class should pass messages to the UI class"""
def __init__(self, messageQueue):
"""Init worker Thread Class"""
self.messageQueue = messageQueue
threading.Thread.__init__(self)
self.start()
def run(self):
"""This code executes when the thread is run"""
KeepRunningStatusThread = True
while KeepRunningStatusThread:
sys.stdout.flush()
try:
msg = self.messageQueue.get()
self.messageQueue.task_done()
except:
pass
if msg == "Shutdown":
# Kill this thread
KeepRunningStatusThread = False
else:
pub.sendMessage("UI", msg=msg)
class UI2(wx.Frame):
"""This class is the UI"""
def __init__(self, taskQueue, messageQueue, stopQueue, parent=None):
self.taskQueue = taskQueue
self.messageQueue = messageQueue
self.stopQueue = stopQueue
wx.Frame.__init__(self, parent, title="TestApp")
#Main panel
sizerMain = wx.BoxSizer(wx.VERTICAL)
# Add the status bar
panelStatusBar = wx.Panel(self)
sizerStatusBar = wx.BoxSizer(wx.HORIZONTAL)
panelStatusBar.SetSizer(sizerStatusBar)
self.StatusBar_Main = wx.StatusBar(panelStatusBar, wx.NewId())
sizerStatusBar.Add(self.StatusBar_Main, 1, wx.EXPAND | wx.LEFT | wx.RIGHT, 2)
#Add the status bar sizer to the main sizer
sizerMain.Add(panelStatusBar, 0, wx.EXPAND)
#Add the progress bar
panelProgressBar = wx.Panel(self)
sizerProgressBar = wx.BoxSizer(wx.HORIZONTAL)
panelProgressBar.SetSizer(sizerProgressBar)
self.Gauge_ProgressBar = wx.Gauge(panelProgressBar, wx.NewId())
sizerProgressBar.Add(self.Gauge_ProgressBar, 1, wx.EXPAND)
sizerMain.Add(panelProgressBar,0,wx.EXPAND)
#Layout the frame
self.SetSizer(sizerMain)
self.SetAutoLayout(1)
sizerMain.Fit(self)
self.Layout()
self.Show(show=True)
#Subscribe to messages from the messageQueue
pub.subscribe(self.HandleStatusUpdate, "UI")
AwaitStatusReportThreadClass(self.messageQueue)
def HandleStatusUpdate(self, msg):
"""
This def updates the UI from a pubsub subscription
"""
StatusBar = self.StatusBar_Main
StatusBar.PushStatusText(msg)
if __name__ == "__main__":
#Make multiprocessing work when app is frozen
multiprocessing.freeze_support()
taskQueue = multiprocessing.JoinableQueue() #Specifies tasks to be completed by the GenInst process
messageQueue = multiprocessing.JoinableQueue() #Holds status messages/progress messages to update the message zone and progress bar in the UI
stopQueue = multiprocessing.JoinableQueue() #Allows cancel operation button to function
messageQueue.put("Please wait while the GenInst background process starts...")
#Start the UI
app = wx.App(False)
frame = UI2(taskQueue=taskQueue, messageQueue=messageQueue, stopQueue=stopQueue)
app.MainLoop()
アドバイスはありますか?