2013-09-24 6 views
13

У меня есть скрипт Python, который обрабатывает асинхронные обратные вызовы от .NET Remoting. Эти обратные вызовы выполняются в фиктивном (рабочем) потоке. Изнутри моего обработчика обратного вызова мне нужно вызвать функцию, определенную в моем скрипте, но мне нужна функция для выполнения в основном потоке.Выполнение функции Python в основном потоке из вызова в потоке Dummy

Главный поток - это удаленный клиент, который отправляет команды на сервер. Некоторые из этих команд приводят к асинхронным обратным вызовам.

В принципе, мне нужен эквивалент метода Invoke .NET. Это возможно?

+0

что делает основной поток делать? вам нужно как-то оповестить его и заставить его вызвать функцию. если основной поток, как правило, ждет, когда что-то произойдет, а затем сообщите об этом. если основной поток выполняет обработку, затем помещает функцию в очередь и проверяет главный поток и обрабатывает очередь изредка. – Claudiu

+0

Добавлена ​​информация для публикации. –

+0

Хммм ... думая больше .... если обратный вызов возникает, когда Main ожидает, что сервер вернет управление из вызова, нет способа заставить Main сделать что-нибудь еще, не так ли? –

ответ

18

Вы хотите использовать класс Queue, чтобы настроить очередь, в которой ваши фиктивные потоки заполняются функциями и что ваша основная нить потребляет.

import Queue 

#somewhere accessible to both: 
callback_queue = Queue.Queue() 

def from_dummy_thread(func_to_call_from_main_thread): 
    callback_queue.put(func_to_call_from_main_thread) 

def from_main_thread_blocking(): 
    callback = callback_queue.get() #blocks until an item is available 
    callback() 

def from_main_thread_nonblocking(): 
    while True: 
     try: 
      callback = callback_queue.get(False) #doesn't block 
     except Queue.Empty: #raised when queue is empty 
      break 
     callback() 

Демо:

import threading 
import time 

def print_num(dummyid, n): 
    print "From %s: %d" % (dummyid, n) 
def dummy_run(dummyid): 
    for i in xrange(5): 
     from_dummy_thread(lambda: print_num(dummyid, i)) 
     time.sleep(0.5) 

threading.Thread(target=dummy_run, args=("a",)).start() 
threading.Thread(target=dummy_run, args=("b",)).start() 

while True: 
    from_main_thread_blocking() 

Печать:

From a: 0 
From b: 0 
From a: 1 
From b: 1 
From b: 2 
From a: 2 
From b: 3 
From a: 3 
From b: 4 
From a: 4 

, а затем блоки навсегда

+0

Очень круто. Python упрощает передачу и хранение делегатов. Я ценю ваш очень подробный ответ. –

+0

@JimC: это часть того, почему это мой любимый язык =). ура – Claudiu