2016-05-14 11 views
3

他のコードを実行しながら同時に他のサーバースレッドからコール/イベントを聴くべき "サーバー"スレッドがある状況があります。最近、私はNode.jsで多くの作業をしていますので、非同期/待機を使用してイベントループを作成して、イベントループで他のスレッドが待機して最終的に参加するときの応答を処理できるようにすることをお勧めします。私は別の文字列と3つのワーカースレッドをキックオフし、それらが終了するのを待ちたいスレッドを待つPython asyncio

# http://stackabuse.com/python-async-await-tutorial/ 
# Testing out Python's asynchronous features 
import asyncio 
from time import sleep 
import threading 
from threading import Thread 
import random 

class MyThread(Thread): 

    def __init__(self, message): 
     Thread.__init__(self) 
     self._message = message 

    def run(self): 
     self._return = self._message + " oli viesti" 
     a = random.randint(1, 5) 
     print("Sleep for ", a) 
     sleep(a) 
     print("Thread exiting...") 


    def join(self): 
     Thread.join(self) 
     return self._return 



async def send(message): 
    t = MyThread(message) # daemon = True 
    t.start() 
    print("asd") 
    return t.join() 

async def sendmsg(msg): 
    response = await send(msg) 
    print("response is ", response) 


if __name__ == "__main__": 
    # Initiate a new thread and pass in keyword argument dictionary as parameters 
    loop = asyncio.get_event_loop() 
    tasks = [ 
     asyncio.ensure_future(sendmsg("hippa1"), loop=loop), 
     asyncio.ensure_future(sendmsg("hippa2"), loop=loop), 
     asyncio.ensure_future(sendmsg("hippa3"), loop=loop) 
    ] 

    loop.run_until_complete(asyncio.wait(tasks)) 
    loop.close() 

の例では:私は、Python 3.5で、次のテストスクリプトを書いたアイデアをテストする

。労働者は無作為に時間を寝るので、スクリプトを複数回実行するとランダムな順番で終了すると思います。最初のスレッドの後に2番目のスレッドが順番に実行されるように見えることが分かります。

ここで私のエラーは何ですか?スレッドをスリープ状態にしないでください。私のイベントループは正しく設定されていますか?ジョインを非同期/待機することはできますか?

最終的に私は他のスレッドにメッセージを送り、その応答が返された値でコールバック関数を実行するのを待ちます。

編集:明確にするために、最終的に私のメインスレッドで条件変数をasync/awaitで待って、条件変数のいくつかが実行されるまで他のコードを実行したい。このコード例では、ワーカースレッドの結合で同じことをしようとしていました。

+0

'time.sleep'は非同期ではありませんが、' await asyncio.sleep'で試してください – jonrsharpe

+0

しかし別のスレッドでトリガされるので、イベントループのメインスレッドではなく別のスレッドをブロックしてはいけませんありますか?私の理解は、スリープはスレッドであり、プロセスのブロックではないということです。だから、なぜjoinブロックがasync/await構造であってもメインスレッドをブロックするのですか? – Tumetsu

答えて

1

結局、原因で、このコードの順番に実行されている:あなたがスレッドを開始

async def send(message): 
    t = MyThread(message) # daemon = True 
    t.start() 
    print("asd") 
    return t.join() 

、その後すぐに続行する前に終了するそのスレッドを待ちます。これが彼らが逐次実行される理由です。

Node.jsとasyncioは、操作を実行するために必ずしも新しいスレッドを作成するとは限りません。たとえば、Node.jsは単一のスレッドしか使用しませんが、カーネルレベルの関数(たとえば 'epoll')を使用して、新しいネットワークアクティビティが発生したときに指定したコールバックを呼び出します。これにより、1つのスレッドで何百ものネットワーク接続を管理できます。

これはおそらく、Threadインスタンスなしでこれを実行したときに、現在実行中のスレッド(メインスレッドと同じ)でsleepを呼び出すためです。 asyncioをネットワーキング関数とともに使用するときは、他のタスクが他のリモートサービスを使っている間に他のコードブロックを実行できるようにする、 "yield from"構造を使用できます。

主な構造は正しいです。あなたは、このコードブロック欲しい:

loop.run_until_complete(asyncio.wait(tasks)) 

をしかし、機能をテストするために「スリープ」に依存しない、あなたはネットワーキング・コール、または利用を行う必要があります。

yield from asyncio.sleep(1) 

そして必要はありませんその場合は別のスレッドを開始します。

+0

スレッド開始の良い点。しかし、私の場合、私は本当に別のスレッドを必要とするが、私は可能であれば* *非同期的にそれらから条件を待ちたいです。だから私は、チェックがイベントループに参加するが、それでも他の任意のコードを実行した場合、ループにブロック解除に参加するまでの機能を持っているしたいと思います。だから、私の場合は、Node.jsのに完全にアナログではなく、私の代わりに非同期イベントループを使用して、私のメインスレッドをブロックせずに/設定条件変数を完了するために他のスレッドを待ちたいです。 降伏t.join私はあなたがすべてでasyncio使用していないことを示唆している場合は() – Tumetsu

+0

要するに、私のような何かを書く方法を見つけ出すことはできません。 task_done()で待ち行列を待ち、get()を使用して作業項目を取り上げることができます。別のキューを使用して結果をメインスレッドに返信することができます。 https://docs.python.org/3/library/queue.html – Tumetsu

+0

が、その間のキューで動作します: – radialmind

関連する問題