2016-10-13 2 views
0

나는 클라이언트 - 서버 응용 프로그램을 작성 중입니다. 연결되어있는 동안 클라이언트는 서버에 "하트 비트"신호 (예 : 매초)를 보냅니다. 서버 측에서 비동기 적으로 실행될 작업 (또는 coroutines 또는 다른 것)을 추가 할 수있는 메커니즘이 필요합니다. 또한, "하트 비트"신호를 보내는 것을 중지하면 클라이언트에서 작업을 취소하고 싶습니다.asyncio를 사용하여 작업을 예약하고 취소하는 방법

즉, 서버가 작업을 시작하면 시간 초과 또는 ttl의 종류가 있습니다 (예 : 3 초). 서버가 "하트 비트"신호를 수신하면 작업이 완료되거나 클라이언트의 연결이 끊어지기 전까지 (신호 전송을 중단 할 때까지) 타이머를 다시 3 초 동안 리셋합니다.

여기 example에서 asyncio 자습서 pymotw.com에서 작업 취소 중입니다. 하지만 여기서는 event_loop이 시작되기 전에 작업이 취소되었으므로 나에게 적합하지 않습니다.

import asyncio 

async def task_func(): 
    print('in task_func') 
    return 'the result' 


event_loop = asyncio.get_event_loop() 
try: 
    print('creating task') 
    task = event_loop.create_task(task_func()) 

    print('canceling task') 
    task.cancel() 

    print('entering event loop') 
    event_loop.run_until_complete(task) 
    print('task: {!r}'.format(task)) 
except asyncio.CancelledError: 
    print('caught error from cancelled task') 
else: 
    print('task result: {!r}'.format(task.result())) 
finally: 
    event_loop.close() 
+0

비동기를 수행하기 위해 샐러리와 같은 것을 사용하는 것을 싫어합니까? –

+0

@KeithBailey 사실, 샐러리가 도움이 될 수 있습니다. 하지만 제 3 파티 라이브러리가 아닌 표준 라이브러리의 일부인 'asyncio'가있는 솔루션이 있다면 훨씬 더 좋을 것입니다. –

+0

셀시에서 어떻게 해야할지 대략 알고 있습니다. asyncio에서 할 수 있어야합니다. 큐 유형 (asyncio 하나 및 다중 처리 탭)을 사용하여 수행하십시오. 큐와 소비자를 정의한 다음 큐에서 항목을 제거 할 수 있습니다. 나는 그것이 당신이 일을 멈추게 할 것이라고 믿지 않는다. –

답변

3

당신은 ensure_future() 방법을 통해 작업을 실행 asyncioTask 래퍼를 사용할 수 있습니다.

ensure_future은 자동으로 코 루틴을 Task 래퍼에 래핑하고 이벤트 루프에 첨부합니다. 따라서 Task 랩퍼는 에서 await까지 코 루틴 '크랭크 오버'를 보장합니다 (또는 코 루틴이 완료 될 때까지).

다른 말로하면 정규 코 루틴을 ensure_future으로 전달하고 그 결과로 Task 개체를 변수에 할당하면됩니다. 그런 다음 중지해야 할 때 Task.cancel()으로 전화 할 수 있습니다.

import asyncio 

async def task_func(): 
    print('in task_func') 
    # if the task needs to run for a while you'll need an await statement 
    # to provide a pause point so that other coroutines can run in the mean time 
    await some_db_or_long_running_background_coroutine() 
    # or if this is a once-off thing, then return the result, 
    # but then you don't really need a Task wrapper... 
    # return 'the result' 

async def my_app(): 
    my_task = None 
    while True: 
     await asyncio.sleep(0) 

     # listen for trigger/heartbeat 
     if heartbeat and not my_task: 
      my_task = asyncio.ensure_future(task_func()) 

     # also listen for termination of hearbeat/connection 
     elif not heartbeat and my_task: 
      if not my_task.cancelled(): 
       my_task.cancel() 
      else: 
       my_task = None 

run_app = asyncio.ensure_future(my_app()) 
event_loop = asyncio.get_event_loop() 
event_loop.run_forever() 

작업은 기본 흐름을 방해하지 않고 백그라운드에서 계속 작동해야하는 장기 실행 작업을위한 것입니다. 필요한 모든 것이 신속한 일회성 메소드라면, 대신 함수를 직접 호출하십시오.

관련 문제