Хотя прерывание потоков может быть невозможным, Deferred можно остановить с помощью функции cancel
, которая, я думаю, доступна в Twisted 10.1.0 и более поздних версиях.
Я использовалследующий класс, чтобы сделать Deferreds, который вызывает конкретную функцию, если Deferred не сработал через некоторое время.Это может быть полезно для кого-то, у кого есть тот же вопрос, который был задан в теме ОП.
РЕДАКТИРОВАТЬ: Как предлагается в комментариях ниже, лучше не наследовать от 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 секунд, и ничего больше.