from twisted.internet import reactor from twisted.internet import threads from twisted.internet import defer import time def worker(arg): print 'Hello world' time.sleep(10) return 1 def run(): print 'Starting workers' l = [] for x in range(2): l.append(threads.deferToThread(worker, x)) return defer.DeferredList(l) def res(results): print results reactor.stop() d = run() d.addCallback(res) reactor.run()
如何通过超时停止工作人员?
答案 0 :(得分:5)
除非与您合作,否则不能中断线程。 time.sleep(10)
不会合作,所以我认为你不能打断这个工人。如果你有另一种具有多个离散阶段的工人,或者在一些任务的循环中操作,那么你可以这样做:
def worker(stop, jobs):
for j in jobs:
if stop:
break
j.do()
stop = []
d = deferToThread(worker)
# This will make the list eval to true and break out of the loop.
stop.append(None)
这也不是Twisted特定的。这就是线程在Python中的工作方式。
答案 1 :(得分:3)
虽然可能无法中断线程,但可以通过cancel
函数停止延迟,我认为这在Twisted 10.1.0及更高版本中可用。
如果Deferred在一段时间后没有触发,我已经使用以下类来使Deferreds回调特定函数。对于那些与OP主题具有相同问题的人来说,这可能是有用的。
编辑:正如下面的评论所建议的那样,最好不要继承defer.Deferred
。因此,我已经将代码更改为使用可实现相同效果的包装器。
class DeferredWrapperWithTimeout(object):
'''
Holds a deferred that allows a specified function to be called-back
if the deferred does not fire before some specified timeout.
'''
def __init__(self, canceller=None):
self._def = defer.Deferred(canceller)
def _finish(self, r, t):
'''
Function to be called (internally) after the Deferred
has fired, in order to cancel the timeout.
'''
if ( (t!=None) and (t.active()) ):
t.cancel()
return r
def getDeferred(self):
return self._def
def addTimeoutCallback(self, reactr, timeout,
callUponTimeout, *args, **kw):
'''
The function 'callUponTimeout' (with optional args or keywords)
will be called after 'timeout' seconds, unless the Deferred fires.
'''
def timeoutCallback():
self._def.cancel()
callUponTimeout(*args, **kw)
toc = reactr.callLater(timeout, timeoutCallback)
return self._def.addCallback(self._finish, toc)
超时之前示例回调:
from twisted.internet import reactor
from DeferredWithTimeout import *
dw = DeferredWrapperWithTimeout()
d = dw.getDeferred()
def testCallback(x=None):
print "called"
def testTimeout(x=None):
print "timedout"
d.addCallback(testCallback)
dw.addTimeoutCallback(reactor, 20, testTimeout, "to")
reactor.callLater(2, d.callback, "cb")
reactor.run()
打印“被叫”,别无其他。
回调前示例超时:
from twisted.internet import reactor
from DeferredWithTimeout import *
dw = DeferredWrapperWithTimeout()
d = dw.getDeferred()
def testCallback(x=None):
print "called"
def testTimeout(x=None):
print "timedout"
d.addCallback(testCallback)
dw.addTimeoutCallback(reactor, 20, testTimeout, "to")
reactor.run()
20秒后打印“timedout”,没有别的。
答案 2 :(得分:0)
好吧,我的答案不是关于线程,但正如所说,你可以将超时功能作为一个单独的帮助器实现:
from twisted.internet import defer
def add_watchdog(deferred, timeout=0.05):
def callback(value):
if not watchdog.called:
watchdog.cancel()
return value
deferred.addBoth(callback)
from twisted.internet import reactor
watchdog = reactor.callLater(timeout, defer.timeout, deferred)
d = defer.Deferred()
add_watchdog(d)
然后,如果需要,您可以将defer.TimeoutError
陷入延迟的错误中。
答案 3 :(得分:0)
我们这样做是使用装饰器。此方法的优点是在达到超时时取消延迟。这应该以某种方式成为Twisted库imho的一部分
FacebookClient client = new FacebookClient();
client.AppId = appId;
client.AppSecret = appSecret;
dynamic result = client.Get("oauth/access_token", new
{
client_id = appId,
client_secret = appSecret,
grant_type = "client_credentials"
});
//client.AccessToken = "";
var accessToken = result.access_token;
client.AccessToken = accessToken;
dynamic parameters = new ExpandoObject();
parameters.client_id = appId;
parameters.redirect_uri = "https://www.facebook.com/connect/login_success.html";
parameters.response_type = "token";
parameters.display = "popup";
parameters.scope = "publish_actions";
var login = client.GetLoginUrl(parameters);
// AccessToken token;
// var accessToken = client.AccessToken;
dynamic result2 = client.Get("me");