You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何等待后台异步回调?分配线程等待回调的实现难题

Got it, let's break down how to solve this problem. You need a dedicated thread running an infinite while loop that waits for an external, out-of-your-control callback—and you tried asyncio.Future without luck. Let's cover why that might have happened, then walk through two solid, straightforward solutions using Python's built-in threading tools.

Solution 1: Use threading.Event for callback triggers

The threading.Event is a thread-safe synchronization primitive perfect for this scenario. It acts like a flag: your worker thread waits for the flag to be set by the external callback, processes the event, then resets the flag to wait for the next trigger.

Here's a concrete example:

import threading
import time

# Thread-safe event to signal when a callback is received
callback_event = threading.Event()
# Store callback data (if you need to pass payloads)
callback_payload = None

def external_triggered_callback(data):
    """This is the callback the remote server will invoke (you don't control when it runs)"""
    global callback_payload
    callback_payload = data
    print(f"Callback fired with data: {data}")
    # Set the event to wake up the waiting worker thread
    callback_event.set()

def worker_thread():
    """Permanent thread running the infinite while loop"""
    print("Worker thread started, waiting for callbacks...")
    while True:
        # Block until the event is set (no timeout = wait forever)
        callback_event.wait()
        
        # Process the callback data
        if callback_payload is not None:
            print(f"Worker processing callback data: {callback_payload}")
            # Reset the event and clear payload for the next trigger
            callback_event.clear()
            callback_payload = None
        
        # Optional: Add any periodic logic you need in the loop
        time.sleep(0.1)

# Start the worker thread (daemon=True lets it exit when the main thread exits)
worker = threading.Thread(target=worker_thread, daemon=True)
worker.start()

# Simulate the remote server triggering the callback (replace this with real external calls)
time.sleep(3)
external_triggered_callback("Sample data from remote server")

# Keep main thread alive for testing
time.sleep(10)

How this works:

  • callback_event.wait() blocks the worker thread until the external callback calls callback_event.set()
  • After processing, we reset the event with clear() so the thread can wait for the next callback
  • The callback_payload variable lets you pass data from the callback to the worker thread (thread-safe here because we only write to it when the event is unset, and read when it's set)

Solution 2: Use queue.Queue for multiple/queued callbacks

If you expect the remote server to trigger callbacks multiple times in quick succession, queue.Queue is a better fit. It handles thread-safe data queuing, so you don't have to manage resetting flags manually.

Example code:

import threading
import queue
import time

# Thread-safe queue to hold callback payloads
callback_queue = queue.Queue()

def external_triggered_callback(data):
    """External callback invoked by the remote server"""
    print(f"Callback received: {data}")
    # Add the data to the queue
    callback_queue.put(data)

def worker_thread():
    """Permanent worker thread with infinite loop"""
    print("Worker thread started, monitoring callback queue...")
    while True:
        # Block until data is available in the queue
        payload = callback_queue.get()
        
        # Process the payload
        print(f"Worker processing: {payload}")
        
        # Mark the task as done (optional, but useful for tracking queue status)
        callback_queue.task_done()
        
        # Optional periodic loop logic
        time.sleep(0.1)

# Start the worker thread
worker = threading.Thread(target=worker_thread, daemon=True)
worker.start()

# Simulate multiple external callbacks
time.sleep(2)
external_triggered_callback("First callback data")
time.sleep(1)
external_triggered_callback("Second callback data")
time.sleep(1)
external_triggered_callback("Third callback data")

# Keep main thread alive
time.sleep(5)

How this works:

  • The external callback adds data to the queue with put()
  • The worker thread uses get() to block until data is available
  • The queue automatically handles thread safety, so you don't have to worry about race conditions between multiple callbacks

Why asyncio.Future might not have worked

asyncio.Future is tied to asyncio's event loop, which runs in a single thread. If you tried to set the Future's result from an external, non-asyncio thread, you likely ran into thread-safety issues—asyncio doesn't allow modifying Futures from outside the event loop thread without special handling (like loop.call_soon_threadsafe). Since your use case requires a dedicated thread with a permanent while loop, using threading primitives is a simpler, more natural fit than forcing asyncio into the mix.

内容的提问来源于stack exchange,提问作者Elrond

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:41:17