• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

trolaro

WxPython - aplicação crasha ao tentar parar uma thread...

12 mensagens neste tópico

Boas. Sou novo por estas bandas. Se me puderem dar uma ajudinha muito obrigado.

Estou a tentar fazer uma interface para um projecto da escola, mas deparei-me com o seguinte problema:

Estou a trabalhar com o GNU Radio, e tenho que capturar uns sinais e ao mesmo tempo mostrar uns gráficos em tempo real. A primeira parte do código e sintonizar o sinal e para isso preciso de usar um while. Para que a interface principal nao bloqueie tenho que correr essa parte numa thread a parte.

O que acontece é que quando tento parar por vezes obtenho este erro:

python: ../../src/xcb_lock.c:77: _XGetXCBBuffer: Assertion `((int) ((xcb_req) - (dpy->request)) >= 0)' failed.
Aborted

Isto acontece ainda mais frequentemente se fechar e correr o programa de novo.

É a primeira vez que faço algo deste género, não me admiro que seja qualquer coisa básica que me esteja a escapar.

Obrigado desde já pela ajuda que me possam dar.

O trecho de código com interesse é este abaixo:

#-----------------------------------------------------------------------#

class Tuner(wx.Frame):

def __init__(self, frame):
	wx.Frame.__init__(self, None, -1, "Tunning Stats")
	self.frame = frame
	self.Stop = False

def StartTune (self):

	#		Frame to display Tunning Evolution
	self.fftwindow = wx.Frame(self.frame,-1, "Tunning",
							style=wx.FRAME_FLOAT_ON_PARENT|wx.CAPTION|wx.CLOSE_BOX,
							pos=(200,170), size=(500,500))
	fftwindow = self.fftwindow

	# Create FFT Plot
	self.plot = wx.lib.plot.PlotCanvas(fftwindow, style=wx.RAISED_BORDER)
	size = fftwindow.GetClientSize()
	self.plot.SetInitialSize(size=size)
	self.plot.SetShowScrollbars(False)
	self.plot.SetEnableZoom(True)
	self.plot.SetFontSizeAxis(point=8)
	self.plot.SetFontSizeTitle(point=15)

	self.winSizer = wx.BoxSizer(wx.VERTICAL)
	self.winSizer.AddSpacer(20)
	self.winSizer.Add(self.plot)
	self.winSizer.AddSpacer(20)
	self.SetSizer(self.winSizer)
	fftwindow.Fit()
	fftwindow.Show()

	# Algum trabalho fictício ( o erro aparece tanto neste exemplo como com a captura de sinal )
	while(1):
		if self.Stop:
			time.sleep(2)       # não sei porque mas parece dar menos erros com o sleep aqui
			print "stop"
			return
		for i in range(100): print i
		for i in range(100): print 100-i


def StopTune(self):
	self.Stop = True

#---------------------------------------------------------------------------------------------#
#				GUI

(....)

#TUNNING INTERFACE

#		Prepare to Start Tunning
def OnTune(self,event):
	self.TuneButton.Enable(False)
	self.StopButton.Enable(True)
	self.SetStatusText("Tunning...")
	self.t = Tuner.Tuner(self)
	self.thread = threading.Thread(target=self.__run)
	self.thread.setDaemon(True)
	self.thread.start()

#		Start Tunnning
def __run(self):
	wx.CallAfter(self.AfterRun)
	self.t.StartTune()
	self.SetStatusText("Tunning Complete...")

#		Free GUI
def AfterRun(self):
	pass

#		Stop Tuner
def OnStop(self, event):
	self.t.StopTune()
	self.TuneButton.Enable(True)
	self.StopButton.Enable(False)
	print "Stoped!"

(.....)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Depois do OnStop fazes alguma coisa? Quando é que acontece o erro? É no momento que fazes o OnStop? É depois? Logo a seguir ou passado um tempo?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

São só dois botões. Start e Stop.

Para já, depois do OnStop simplesmente paro o ciclo. E se quiser recomeço a sintonizaçao no botão Start.

O erro acontece quanto forço a paragem. Estive a testar com um ciclo não infinito e corre bem se deixar ir até ao fim. Se tentar pará-lo a meio por vezes acontece o que expliquei.

Acho que tem que ver com a maneira como estou a tentar parar o ciclo. Já reparei que se fechar a janela principal, depois de ter iniciado e parado uma sintonização, a thread da GUI mantem-se na lista de processos. Se nunca tiver efectuado uma sintonização deixa de aparecer na lista como devia de ser.

Experimentei fazer kill ao terminar a GUI e resolve a parte do problema de quando reinicio o programa.

Mas a parte de forçar a paragem da sintonização continua a falhar.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Eu estava a ter esse problema com WxPython também não sei de é a melhor maneira ou a mais correcta mas funciona, mata todas as thread quando fechas o Gui, logo esse erro nao deve aparecer mais no init adiciona a linha :thumbsup:


def OnClose(self, a=None):
    os._exit(0)

def __init__():
    self.Bind(wx.EVT_CLOSE, self.OnClose)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Obrigado pela dica ao fechar a GUI.  :thumbsup:

No final a sintonização vai ser feita de forma automática. Mas a seguir vem um processo de aquisição de dados que poderá correr ao longo de dias ou meses, sem interrupção. Só deve ser parado a pedido ou quando a luz vai abaixo ;).

Por isso ainda tenho que por a funcionar a paragem forçada tanto da sintonização como da aquisição. ( Fazendo uma faz-se a outra )

Se me souberes dizer como parar o ciclo de sintonização/aquisição sem correr o risco do programa crashar ficava agradecido.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O erro acontece quanto forço a paragem. Estive a testar com um ciclo não infinito e corre bem se deixar ir até ao fim. Se tentar pará-lo a meio por vezes acontece o que expliquei.

Que queres dizer quando forças a paragem? É quando carregas no botão Stop?

Chega a executar isto: print "Stoped!" ?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Sim. Imprime o "Stoped!".

No ciclo tenho esta verificação:

if self.Stop:

if fftwindow:

fftwindow.Destroy()

break

Passados uns segundos, provavelmente depois de correr a este pedaço de código, é que crasha e fecha GUI.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

ve se não tens alguma chamada a janela depois de destruída......

isso provavelmente ia causar o erro :thumbsup:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

if self.Stop:

if fftwindow:

fftwindow.Destroy()

break

Onde é que está isso? Não encontro no pedaço de código que puseste originalmente.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Onde é que está isso? Não encontro no pedaço de código que puseste originalmente.

# Algum trabalho fictício ( o erro aparece tanto neste exemplo como com a captura de sinal )

while(1):

    if self.Stop:

            time.sleep(2)      # não sei porque mas parece dar menos erros com o sleep aqui

            print "stop"

            return

    (....)

Está neste ciclo, mas como no final tenho uma janela criada, para além disso tenho o pedaço que mostrei para a fechar.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Podias mostrar o ciclo completo?

Estar a mostrar o ciclo aos retalhos não é muita boa ideia quando se tenta analisar o código.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

ve se não tens alguma chamada a janela depois de destruída......

isso provavelmente ia causar o erro :)

Parece que ja consegui resolver o problema.

O código para actualizar o gráfico estava na thread que tentava parar. E parece que mesmo depois de mandar parar ela ainda tentava redesenhar o gráfico depois dele ter sido destruido.

Alterei o programa de maneira a que a thread principal actualize o gráfico e a secundária apenas forneça os dados. E adicionei um pedaço de código para gerar um evento que avisa a principal que ja pode actualizar.

Agora deixou de dar erros ao cancelar. Obrigadão pela dica  :P

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora