Python的Twisted中LoopingCall和callInThread的区别

2024-10-01 11:24:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我想弄清楚任务.循环调用还有一个反应器在扭曲。在

所有我的自发送线立即执行循环调用中的。 卡林瑟德的那些不是。只有在循环呼叫结束后才会发送。即使我发送了正确的分隔符。在

为什么?有什么区别?它们不是都是线吗?在

这是服务器:


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()

这是客户:

^{pr2}$

Tags: fromtestimportselfuidiftimedef
2条回答

你看过docsdocs了吗?不涉及线程,它在主线程(通常是reactor的线程)上运行(每秒钟一次,就像调用它的start方法一样)。callInThread是导致函数在单独线程上运行的两种方法中的唯一一种。在

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

否,LoopingCall使用^{};它在reactor中运行调用。在

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

是的,应该是这样。在

The ones in the callInThread are not.

并不是说它们没有被执行,而是因为你从一个线程调用了reactor-API,而你从来都不允许这样做,所以你把你的程序置于一个状态,所有的东西都被彻底破坏了,永远都是。以后的每个API调用都可能产生奇怪的、损坏的结果,或者没有结果,或者随机、无法解释的崩溃。在

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

重复一下:twisted中的每个API,除了^{}(以及通过扩展调用callFromThread,比如^{})之外的每个API都是线程安全的。不幸的是,如果你在这两个API中设置一个单独的API,你会发现这两个API都有一个奇怪的问题。在

如果您有一些代码在需要调用reactor API的线程中运行,请使用callFromThread或{},它将把调用分派到reactor线程,在那里所有的工作都应该顺利。但是,对于定时调用之类的东西,实际上根本不需要使用线程,它们会不必要地使程序复杂化。在

相关问题 更多 >