gpt4 book ai didi

python - Python 的 Twisted 中 LoopingCall 和 callInThread 的区别

转载 作者:太空宇宙 更新时间:2023-11-04 09:20:33 30 4
gpt4 key购买 nike

我试图找出 Twisted 中 task.LoopingCall 和 reactor.callInThread 之间的区别。

我在 LoopingCall 中的所有 self.sendLine 都会立即执行。callInThread 中的那些不是。它们仅在 LoopingCall 中的调用结束后发送。即使我发送了正确的分隔符。

这是为什么呢?有什么不同?它们不都是线程吗?

这是服务器:


from twisted.internet import reactor, protocol, task
from twisted.protocols import basic
from twisted.python import log
import sys
import time
import threading
import Queue

class ServerProtocol(basic.LineOnlyReceiver):
delimiter = '\0'
clientReady = 1

def __init__(self):
print 'New client has logged on. Waiting for initialization'

def lineReceived(self, line):
if line.startswith('I'):
print 'Data started with I: '+line
user = dict(uid=line[1:6], x=line[6:9], y=line[9:12])
self.factory.users[user['uid']] = user
log.msg(repr(self.factory.users))
self.startUpdateClient(user)
reactor.callInThread(self.transferToClient)
self.sendLine(user['uid'] + ' - Beginning - Initialized')
print user['uid'] + ' - Beginning - Initialized'
elif line.startswith('P'):
print 'Ping!'
elif line[0:3] == 'ACK':
print 'Received ACK'
self.clientReady = 1
#else:
#self.transport.loseConnection()

def _updateClient(self, user):
if self._running == 0:
self._looper.stop()
return
self._running -= 1
self._test += 1
print user['uid'] + ' Sending test data' + str(self._test)
self.sendLine(user['uid'] + ' Test Queue Data #%d' % (self._test,) + '\0')

def startUpdateClient(self, user):
self._running, self._test = 25, 0
self._looper = task.LoopingCall(self._updateClient, user)
self._looper.start(1, now=False)
print user['uid'] + ' - Startupdateclient'

def transferToClient(self):
test = 20
while test > 0:
if self.clientReady == 1:
test = test-1
print 'Reactor test ' + str(test) + ' - ' + str(time.time())
self.clientReady = 0
self.sendLine('This is reactortest ' + str(test) + ' - ' + str(time.time()) +' \0')

class Server(protocol.ServerFactory):
protocol = ServerProtocol
def __init__(self):
self.users = {}

if __name__ == '__main__':
log.startLogging(sys.stderr)
reactor.listenTCP(2000, Server())
reactor.run()

这是客户端:


#!/usr/bin/env python

import socket
import time

host = 'localhost'
port = 2000
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
s.send('I12345070060\0')
running = 1

while running:
s.send('ACK\0')
data = s.recv(size)
if data:
print 'Received:', data
else:
print 'Closing'
s.close()
running=0

最佳答案

Why is that? What's the difference? Aren't they both threads?

没有。 LoopingCall 使用 callLater ;它在 react 器中运行调用。

All my self.sendLine's in the LoopingCall are performed immediately.

是的,他们应该是。

The ones in the callInThread are not.

与其说它们没有被执行,还不如说是因为你从一个线程调用了一个 react 器 API,而你从来没有被允许这样做,你已经把你的程序放到了一个线程中状态一切都彻底崩溃,永远。 future 的每次 API 调用都可能产生奇怪的、损坏的结果,或者没有结果,或者随机的、莫名其妙的崩溃。

您知道,多线程程序的正常工作方式 ;-)。

重复一下:每个 API 都是扭曲的,唯一的异常(exception)是 callFromThread (以及调用 callFromThread 的扩展,如 blockingCallFromThread ),不是线程安全的。不幸的是,为每个 API 都设置警告既是代码维护的噩梦,因此一些用户通过调用 API 并注意到一些奇怪的事情,以与您相同的方式发现了这个约束。

如果您有一些代码在需要调用 react 器 API 的线程中运行,请使用 callFromThreadblockingCallFromThread,它会将调用分派(dispatch)给 react 器线程,一切都应该顺利进行。但是,对于像定时调用这样的事情,实际上根本不需要使用线程,它们会使您的程序不必要地复杂化。

关于python - Python 的 Twisted 中 LoopingCall 和 callInThread 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3220991/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com