Soru Python'da geri arama yöntemi nasıl iletilir ve çalıştırılır


Çeşitli işlemlerin üstesinden gelmek için diğer konuları oluşturan bir Yöneticisi (ana iş parçacığı) sahibim. Yöneticimin, oluşturduğu bir iş parçacığı sona erdiğinde bildirilmesini isterim (run () yöntemi yürütme bittiğinde).

Thread.isActive () yöntemi ile tüm thread'ların durumunu kontrol ederek yapabileceğimi biliyorum, ama yoklama berbat, bu yüzden bildirim almak istedim.

Threads'a geri arama yöntemi vermeyi düşünüyordum ve run () yönteminin sonunda bu işlevi çağırıyorum:

class Manager():
    ...
    MyThread(self.on_thread_finished).start() # How do I pass the callback

    def on_thread_finished(self, data):
        pass
    ...

class MyThread(Thread):
    ...
    def run(self):
        ....
        self.callback(data) # How do I call the callback?
    ...

Teşekkürler!


21
2017-07-23 14:22


Menşei


Dişli olmayan geri arama yöntemi örneğiyle ilgileniyorum. - ThorSummoner


Cevaplar:


İş parçacığı, yöneticiye bir atıfta bulunmadığı sürece yöneticiyi arayamaz. Bunun gerçekleşmesi için en kolay yol, yöneticinin somutlaştırmada iş parçacığına vermesidir.

class Manager(object):
    def new_thread(self):
        return MyThread(parent=self)
    def on_thread_finished(self, thread, data):
        print thread, data

class MyThread(Thread):

    def __init__(self, parent=None):
        self.parent = parent
        super(MyThread, self).__init__()

    def run(self):
        # ...
        self.parent and self.parent.on_thread_finished(self, 42)

mgr    = Manager()
thread = mgr.new_thread()
thread.start()

Yönetici nesnesine bir başvuru kaydetmek yerine, isteğe bağlı bir işlevi veya yöntemi geri çağırma olarak atayabilmek istiyorsanız, bu yöntem, yöntem sarmalayıcıları ve benzerleri nedeniyle biraz sorunlu hale gelir. Geri bildirimi tasarlamak zor olduğundan, hem yöneticiye hem de ve İstediğiniz şey olan iş parçacığı. Bir süredir bunun üzerinde çalıştım ve kullanışlı veya zarif düşündüğüm bir şeyle gelmedim.


17
2017-07-23 16:06



Son satır olmamalı thread.start()? Aksi takdirde, gerçek bir çoklu okuma oluşmaz ve MyThread.run() başka bir işlev gibi idam edilir. Ama eğer koşarsan MyThread.start() ve yeni bir konu oluşturmak self.parent.on_thread_finished(self, 42) hala ana iş parçacığı yerine yeni iş parçacığının içeriğinde yürütülür. Bir tür senkronizasyona ihtiyacınız olacak, kuyruk, yani @ jonathan-lillesæter aslında doğrudur. - iliis
Python'a yeni. Bu mirasın kötüye kullanılması değil mi? MyThread mantıklı bir çocuk gibi görünmüyor Manager. - Josh Noe
MyThread çocuk değil Manager. - kindall
Bu çözümü kullanmanın, ana iş parçacığı değil, ikincil iş parçacığı içinde geri arama işlevini yürüteceğini bilmem gerektiğini düşünüyorum. Ayrıca, değerlendirmenin kullanımı nedir? self.parent işlevde run ? Önlemek için mi self.parent.on_thread_finished denir parent olduğu None ? Bunu neden kullanmak yerine if Beyan ? Bu kafa karıştırıcı... - Sindarus


Bu şekilde yapmak yanlış mı?

from threading import Thread

class Manager():
    def Test(self):
        MyThread(self.on_thread_finished).start()

    def on_thread_finished(self, data):
        print "on_thread_finished:", data

class MyThread(Thread):
    def __init__(self, callback):
        Thread.__init__(self)
        self.callback = callback

    def run(self):
        data = "hello"
        self.callback(data)

m = Manager()
m.Test() # prints "on_thread_finished: hello"

9
2017-07-25 10:58



Yerel yöntem iki argümanı aldığından, yerel yöntemi on_thread_finished için geri arama olarak iletemezsiniz. Geri arama iplikten çağrıldığında, sadece bir argüman verecektir (veri) - Bharathwaaj
Bunun geç olduğunu biliyorum, ama büyük bir kod parçası yeniden yazmak için bir saat geçirmek üzere olan herkes için: Bharathwaaj'ın yorumu: tamamen yanlışve bu cevap mükemmel çalışıyor. - Shariq
@Shariq, sorun şu ki on_thread_finished hala çocuk ipliğinde çalışır, Manager. Yapamazsın Manager yap çünkü Manager olduğu başka bir şey yapmak şu anda. Sorunu görmek için Test() aradıktan sonra ölü bir döngüde asmak MyThread(). Alternatif olarak, bir yerel değişken tanımlayın ve bunu kullanarak kullanmayı deneyin. on_thread_finished(), Örneğin. number_of_threads_running -=1 - bytebuster
Bu yönetici bir denetleyici GUI'sinde çalışıyorsa, GUI'nin işlevlerini bir iş parçacığından arayamazsınız. - Jason


Ana iş parçacığının alt iş parçacıklarının yürütme işlemini bitirmesini beklemesini istiyorsanız, bir çeşit senkronizasyon mekanizması kullanmanız daha iyi olacaktır. Bir veya daha fazla iş parçacığının çalışması bittiğinde bildirilmek isteniyorsa, Şart yeterlidir:

import threading

class MyThread(threading.Thread):
    def __init__(self, condition):
        threading.Thread.__init__(self)
        self.condition = condition

    def run(self):
        print "%s done" % threading.current_thread()
        with self.condition:
            self.condition.notify()


condition = threading.Condition()
condition.acquire()

thread = MyThread(condition)
thread.start()

condition.wait()

Ancak, bir kuyruk Birden çok çalışan iş parçacığı işlemek biraz daha kolay olduğu gibi, muhtemelen daha iyidir.


3
2017-07-23 17:20