繁体   English   中英

如何从线程中异步获取返回值?

[英]How to get a return value from a thread, asynchonously?

我的问题:启动一个线程 function 并异步地对返回的值进行操作

我知道如何:

  • threading启动一个带螺纹的 function 。 问题:没有简单的方法可以返回结果
  • 从线程 function 获取返回值 问题:它是同步的

我想要实现的类似于 JavaScript 的

aFunctionThatReturnsAPromise()
  .then(r => {// do something with the returned value when it is available})
// the code here runs synchronously right after aFunctionThatReturnsAPromise is started

在伪 Python 中,我会考虑类似(修改示例从答案到链接线程)

import time
import concurrent.futures

def foo(bar):
    print('hello {}'.format(bar))
    time.sleep(10)
    return 'foo'

def the_callback(something):
    print(f"the thread returned {something}")

with concurrent.futures.ThreadPoolExecutor() as executor:
    # submit the threaded call ...
    future = executor.submit(foo, 'world!')
# ... and set a callback
future.callback(the_callback, future.result())  # ← this is the made up part
# or, all in one: future = executor.submit(foo, 'world!', callback=the_callback) # in which case the parameters probably would need to be passed the JS way
# the threaded call runs at its pace
# the following line is ran right after the call above
print("after submit")
# after some time (~10 seconds) the callback is finished (and has printed out what was passed to it)
# there should probably be some kind of join() so that the scripts waits until the thread is done

如果可能的话,我想保留线程(它们按照自己的节奏做事,我不在乎它们什么时候完成),而不是asyncio (我必须在单个线程中明确地await事情)

您可以使用concurrent.futures库的add_done_callback ,因此您可以像这样修改您的示例:

def the_callback(something):
    print(f"the thread returned {something.result()}")
 
with concurrent.futures.ThreadPoolExecutor() as executor:
    future = executor.submit(foo, 'world!')
    future.add_done_callback(the_callback)

您可以使用concurrent.futures.dd_done_callback ,如下所示。 回调必须是一个可调用的,采用单个参数,即Future实例——它必须从中获取结果,如图所示。 该示例还向其中添加了一些附加信息,回调 function 用于打印其消息。

请注意,回调函数将被同时调用,因此如果涉及共享资源,则应采取通常的互斥预防措施。 示例中没有这样做,因此有时打印的 output 会混乱。

from concurrent import futures
import random
import time

def foo(bar, delay):
    print(f'hello {bar} - {delay}')
    time.sleep(delay)
    return bar

def the_callback(fn):
    if fn.cancelled():
        print(f'args {fn.args}: canceled')
    elif fn.done():
        error = fn.exception()
        if error:
            print(f'args {fn.args}: caused error {erro}')
        else:
            print(f'args {fn.args}: returned: {fn.result()}')

with futures.ThreadPoolExecutor(max_workers=2) as executor:
    for name in ('foo', 'bar', 'bas'):
        delay = random.randint(1, 5)
        f = executor.submit(foo, name, delay)
        f.args = name, delay
        f.add_done_callback(the_callback)

print('fini')

样品 output:

hello foo - 5
hello bar - 3
args ('bar', 3): returned: bar
hello bas - 4
args ('foo', 5): returned: foo
args ('bas', 4): returned: bas
fini

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM