【问题标题】:How to pass/exchange data from asynchronous methods/threads?如何从异步方法/线程传递/交换数据?
【发布时间】:2019-06-03 17:21:26
【问题描述】:

有人能解释一下如何在 python 中的异步调用之间传递数据背后的概念吗?

我有这种情况:
我有一个主程序(主线程),然后我运行另一个异步调用,添加两个数字()并休眠一段时间。期望是让主线程等到 calc 和 sleep 完成。就伪代码而言,这可能如下所示:

def example():
    def my_calc(x,y):
        z = x+ y
        time.sleep(2)
        return z  #this should get pushed to queue, but for simplicity we use 'return z'

    z = asyncSomething.callInThread(my_calc, 2, 20)  #assume we get z from queue
    return z+10

def runner():  #our main function
    print 'start'
    z = example()
    print 'result is {0}'.format(z)

如何让最后一个print 等待z?我尝试使用 threading.Event() 并使用 setwaitclear,但它们阻止了一切。

我不认为我的案例是独一无二的,必须有一个简洁的系统方法来处理它。我研究了扭曲的反应堆,但它部分成功。我的实际代码涉及 GUI,它必须等待异步进程的结果,然后自我更新和自动更新......但我认为这个例子描述了大部分问题

我想我错过了如何在 python 中异步工作的实际概念。

【问题讨论】:

  • 您使用的是 Python 2 吗?看起来 Python 3 的 async 和 await 关键字在这里无济于事._.
  • @Geetransit,它是 2.7。我用'async'比喻而不是字面意思
  • 你在 2019 年甚至使用 python 2.7 有什么原因吗?
  • @opa,我使用的生态系统在 2019 年仍在使用 2.7;因此我的问题

标签: python multithreading python-2.7 asynchronous


【解决方案1】:

如果您的主线程在没有来自工作线程的结果的情况下已经尽可能有意义地进行并且您想要阻止,您可以使用threading.Event 等待工作线程执行中的某个点或@987654322 @(其中threadthreading.Thread 实例)等待工作线程完成:

class Example(object):
    def my_calc(self, x, y):
        time.sleep(2)
        self._z = x + y # or push the result to a queue

    def example(self):
        thread = threading.Thread(target=self.my_calc, args=(2, 20))
        thread.start()
        # any other useful work could go here while the worker runs
        thread.join()
        return self._z + 10 # or grab the result from a queue

def runner():
    print "start"
    z = Example().example()
    print "result is {0}".format(z)

但是,在 GUI 的上下文中,您的主线程不太可能已经尽其所能 - 它可能一直忙于保持 GUI 响应。在这种情况下,正如问题的 cmets 中所提到的,最好在工作人员的计算完成后将您想要完成的任何事情打包到工作线程调用的回调中:

def my_calc(x, y):
    time.sleep(2)
    return x + y

def my_calc_thread(x, y, callback):
    z = my_calc(x, y)
    # depending on your GUI framework, you may need to do something
    # like call_in_main_thread(callback, z) if callback touches GUI
    # elements
    callback(z)

def example():
    def finish(z):
        print "result is {0}".format(z)
    t = threading.Thread(target=my_calc_thread, args=(2, 20, finish))
    t.start()

def runner():
    print "start"
    example()

【讨论】:

  • 我的 MainThread 托管 GUI,即 GUI 使用主线程。我在 MainThread 中启动了另一个框架(状态框架),它也在 MainThread 中。在我们拥有的 python 风格中,我们只能将 GUI 启动到 MainThread。然后我使用扭曲反应器让另一个线程同时进行计算和更新状态帧。所有的作品,除了 mainThread 似乎没有等待扭曲的线程(这是完全有意义的)。当我停止 mainThread(通过 .wait())然后整个执行停止(主线程和扭曲线程)-
【解决方案2】:

如果你使用多线程,你应该使用futures 来封装你的结果。具体来说,future.result(timeout=None) 将用于您的情况:

返回调用返回的值。如果调用尚未完成,则此方法将等待 timeout 秒。如果调用在timeout 秒内未完成,则将引发concurrent.futures.TimeoutErrortimeout 可以是 intfloat。如果没有指定timeoutNone,则等待时间没有限制。

如上面的 cmets 中所述,如果您不使用多线程(并且正在使用异步编程),那么回调将是可行的方法。

【讨论】:

    猜你喜欢
    • 2019-03-22
    • 2010-12-16
    • 2016-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多