[PyQt] how to set up a timer to call a method after a delay?
Phil Thompson
phil at riverbankcomputing.com
Thu Jul 1 09:55:17 BST 2010
On Thu, 01 Jul 2010 01:37:00 -0700, Steve Castellotti <sc at puzzlebox.info>
wrote:
> On Thu, 2010-07-01 at 09:09 +0100, Phil Thompson wrote:
>> > I'm still getting this error:
>> >
>> > QObject::startTimer: QTimer can only be used with threads started with
>> > QThread
>>
>> I think that is a misleading message - you need to provide a test case.
>>
>> Because Qt sockets are handled with the event loop you usually do not
>> need
>> to use threads to handle multiple connections.
>
>
> Thanks again for the replies.
>
>
> I've got my server (and test client) working to the point where it
> handles multiple connections and disconnections, though there is still
> some cleanup work left around things like timeouts.
>
>
> I'm not 100% certain I'm doing everything "right" but here's roughly how
> it looks now (translated to pseudo code):
>
>
> class server:
> def __init__(self, parent=None):
> self.connections = []
> self.packet_queue = []
> self.socket = QtNetwork.QTcpServer()
> self.socket.newConnection.connect(self.processConnection)
> self.updateTimer = QtCore.QTimer()
> QtCore.QObject.connect(self.updateTimer, QtCore.SIGNAL("timeout()"),
> self.timerEvent)
> self.updateTimer.start(1000)
>
>
> def processConnection(self):
> client = self.socket.nextPendingConnection()
> client.disconnected.connect(self.deleteDisconnected)
> self.connections.append(client)
>
>
> def deleteDisconnected(self):
> index = 0
> for connection in self.connections:
> state = connection.state()
> if ((state != QtNetwork.QAbstractSocket.ConnectingState) and \
> (state != QtNetwork.QAbstractSocket.ConnectedState)):
> connection.deleteLater()
> del(self.connections[index]
> index += 1
>
>
> def timerEvent(self):
> if self.connections != []:
> self.updateStatus()
> self.sendPacketQueue()
>
>
> def sendPacketQueue(self):
> while (len(self.packet_queue) > 0):
> packet = self.packet_queue[0]
> del self.packet_queue[0]
> index = 0
> for connection in self.connections:
> state = connection.state()
> if state == QtNetwork.QAbstractSocket.ConnectedState:
> self.sendResponse(connection, packet)
> index += 1
>
>
>
> ... where "sendResponse" handles the actual data preparation for
> transmission and writing to the connected socket, and "updateStatus"
> appends packets of data to the packet_queue.
>
>
> I'm not sure if its wise to delete all connections which aren't either
> in a Connected or Connecting state when any single one disconnects, but
> otherwise I couldn't figure out how to track connections and make sure
> all references to a disconnecting client were deleted. For example if I
> just attached "deleteLater" directly to the client.disconnect signal,
> the reference would remain in the self.connections list and next time
> the timer came around to call sendPacketQueue I would get a segfault.
>
>
> For the moment it seems to be behaving well but I would be curious to
> know if there's a smarter way to handle managing multiple connected
> clients.
I don't see why you are using a timer at all - it can only slow things
down. Have you looked at the loopback.py example included with PyQt?
Phil
More information about the PyQt
mailing list