两个或多个协程可以等待 Twisted 中的同一个 Deferred 吗?
Can two or more coroutines await for the same Deferred in Twisted?
我正在尝试使用 deferred 向可能正在等待它的多个协程发出任务结束信号。我想要 threading.Event
中事件的相同行为。协程等待,但只有一个协程得到延迟触发的结果。代码示例:
from twisted.internet import defer, task, reactor
async def test(d):
print("Awaiting")
print(f"Await finished: {await d}")
d = defer.Deferred()
defer.ensureDeferred(test(d))
defer.ensureDeferred(test(d))
task.deferLater(reactor, 1, d.callback, 'Deferred Fired')
reactor.run()
输出:
Awaiting
Awaiting
Await finished: Deferred Fired
Await finished: None
我期待:
Awaiting
Awaiting
Await finished: Deferred Fired
Await finished: Deferred Fired
但是当一个协程等待两次或更多次时它工作正常:
async def test(d):
print("Awaiting")
print(f"Await finished: {await d}")
print(f"Await finished: {await d}")
d = defer.Deferred()
defer.ensureDeferred(test(d))
task.deferLater(reactor, 1, d.callback, 'Deferred Fired')
您正在尝试使用 deferreds 作为一种同步方法,但这并不是它真正的预期目的,至少不是它自己的目的。我假设您想像使用 Event.wait()
一样使用 Deferred
?这是我经常看到的范例:
from dataclasses import dataclass, field
from typing import List
from twisted.internet import defer, reactor
@dataclass
class Thing:
deferred_list: List[defer.Deferred] = field(default_factory=list)
def notifyFinished(self) -> defer.Deferred:
deferred = defer.Deferred()
self.deferred_list.append(deferred)
return deferred
def finish(self):
for index, deferred in enumerate(self.deferred_list):
deferred.callback(index + 1)
self.deferred_list = []
async def doSomethingElse(d):
print("[!] awaiting...")
print(f"[x] done waiting: {await d}")
def main():
thing = Thing()
for _ in range(5):
d = thing.notifyFinished()
defer.ensureDeferred(doSomethingElse(d))
reactor.callLater(5, thing.finish)
reactor.run()
main()
这里我们有一个函数 returns a deferred/future(即 notifyFinished
),跟踪那些被推迟的,一旦一个工作完成,调用一个函数来发出信号作业结束(即 finish
)。 Deferred
旨在仅触发一次(Future
也可能,但不要引用我的话),因此使用此方法可确保返回单个 Deferred
对象并同时触发时间。
我正在尝试使用 deferred 向可能正在等待它的多个协程发出任务结束信号。我想要 threading.Event
中事件的相同行为。协程等待,但只有一个协程得到延迟触发的结果。代码示例:
from twisted.internet import defer, task, reactor
async def test(d):
print("Awaiting")
print(f"Await finished: {await d}")
d = defer.Deferred()
defer.ensureDeferred(test(d))
defer.ensureDeferred(test(d))
task.deferLater(reactor, 1, d.callback, 'Deferred Fired')
reactor.run()
输出:
Awaiting
Awaiting
Await finished: Deferred Fired
Await finished: None
我期待:
Awaiting
Awaiting
Await finished: Deferred Fired
Await finished: Deferred Fired
但是当一个协程等待两次或更多次时它工作正常:
async def test(d):
print("Awaiting")
print(f"Await finished: {await d}")
print(f"Await finished: {await d}")
d = defer.Deferred()
defer.ensureDeferred(test(d))
task.deferLater(reactor, 1, d.callback, 'Deferred Fired')
您正在尝试使用 deferreds 作为一种同步方法,但这并不是它真正的预期目的,至少不是它自己的目的。我假设您想像使用 Event.wait()
一样使用 Deferred
?这是我经常看到的范例:
from dataclasses import dataclass, field
from typing import List
from twisted.internet import defer, reactor
@dataclass
class Thing:
deferred_list: List[defer.Deferred] = field(default_factory=list)
def notifyFinished(self) -> defer.Deferred:
deferred = defer.Deferred()
self.deferred_list.append(deferred)
return deferred
def finish(self):
for index, deferred in enumerate(self.deferred_list):
deferred.callback(index + 1)
self.deferred_list = []
async def doSomethingElse(d):
print("[!] awaiting...")
print(f"[x] done waiting: {await d}")
def main():
thing = Thing()
for _ in range(5):
d = thing.notifyFinished()
defer.ensureDeferred(doSomethingElse(d))
reactor.callLater(5, thing.finish)
reactor.run()
main()
这里我们有一个函数 returns a deferred/future(即 notifyFinished
),跟踪那些被推迟的,一旦一个工作完成,调用一个函数来发出信号作业结束(即 finish
)。 Deferred
旨在仅触发一次(Future
也可能,但不要引用我的话),因此使用此方法可确保返回单个 Deferred
对象并同时触发时间。