2017-08-12 55 views
0

对不起,我不知道如何描述我想要做的单个句子。基本上我每个对象都有足够快的速度,一次创建1个就不会阻塞,但是如果我有一个或几百个,那么它会阻止主循环。我正试图找到一种方法来减少加载对象时发生的口吃量。从本质上讲,我的应用程序必须渲染每一帧,并且如果任何东西长于一帧,应用程序开始出现抖动。Python无阻塞的扭曲异步调度

主要问题是,当我创建对象时,他们必须从json文件中查找数据并导入它。现在每个json文件本身都很快(0.006s),比一帧的1/60快。但是,当计数器开始变为x * 0.006时,就成了问题。

有趣的是,如果我使用类似deferToThread的东西它仍然阻止主循环。这是我想要做的。我希望即时提供对象,因为立即完成它们非常重要。然而,实际的json加载并不重要,我想以某种方式安排它,让其他人开始“填充”,以便在可用时进行发言。它们的可用顺序也是不必要的。

from twisted.internet import reactor, defer 
from profilehooks import profile 
import json 

objects = [] 

def print_test(text): 
    print text 

class JsonObject(object): 
    def __init__(self, i): 
     self.i = i 
     self.json_data = None 
     self.load() # <load data slowly somehow?> 
     # Threads not working either? 
     #d = threads.deferToThread(self.load) 
     #d.addCallback(self.set_json_data) 

    def load(self): 
     with open("{0}.json".format(str(self.i).zfill(3))) as f: 
      self.json_data = json.load(f) 
     #return self.json_data 


    def set_json_data(self, data): 
     print "GOT DATA", self.i 

def load_objects(): 
    for i in xrange(300): 
     objects.append(JsonObject(i)) 

    print "LOADED ALL OBJECTS" 

reactor.callLater(0, load_objects) 
reactor.callLater(0.5, print_test, "test for blocking") 
reactor.run() 
+0

尝试reactor.callLater(0.1,self.load())? –

+0

试过,结果也一样。 – Charlie

+0

对不起,现在在这里已经很晚了,现在我无法想到任何有用的东西......我通常会把一些我不想干涉主程序的东西放到子程序中。你有想过吗? –

回答

0

基本上for i in xrange(300)阻止你的主反应堆。这是一个简单的方法,可以在你的load_objects函数中稍微休息一下,并将控制返回到reactor/event循环,以便完成其他任务。

@defer.inlineCallbacks 
def load_objects(): 
    for i in xrange(300): 
     objects.append(JsonObject(i)) 

     if i % 100 == 0: 
      yield # take a break and let reactor do other tasks 

     print("LOADED ALL OBJECTS") 

另外还有的cooperate功能,做类似的事情,但我总是发现inlineCallbacks更加直观。

+0

对不起,我不清楚,是的,我意识到我提供的例子会因为对象的数量而被阻塞。它会阻止它,因为对象在init上执行self.load()。如果我删除'self.load',它会立即加载。我想要做的就是加载所有的JsonObject(因为它们本身就是快速的,没有初始化时的加载函数),但是它拥有它,所以每个人都安排了一个对self.load的调用,这个调用将被“分散”它不会阻止。 – Charlie

+0

这就是这个答案。这也是合作()会做的。与合作()(这使得它更好)的区别在于它可以完成基于时间的工作块,而不是对某些数字进行硬编码(这可能太多了 - 会导致你口吃 - 或者太少 - 使得这个过程需要更长的时间。) –

+0

另外,deferToThread应该可以正常工作,但是你没有发布任何使用deferToThread的代码,所以很难说你可能做了什么错误。 –