머리말
최근에는 윈도우 클라이언트에서 시작되는 비동기 멀티태스킹 요청을 요구하는 프로젝트가 있는데, 장기간의 백그라운드 작업이 포그라운드 작업을 차단하는 것을 방지하기 위해 멀티 스레드를 시작하여 UI 메인 인터페이스 이벤트 루프와 asyncio 백그라운드 비동기 작업 이벤트 루프.
지원 라이브러리 소개
1. 비동기 코루틴 라이브러리 asyncio
asyncio
코루틴을 사용하여 이벤트 루프를 구현하여 비동기 작업의 효과를 얻으세요.
pip install asyncio
코루틴은 데코레이터를 사용하여 @asyncio.coroutine
비동기 작업을 표시하고 yield from
비동기 작업이 완료될 때까지 기다립니다. ~에
@asyncio.coroutine === 비동기
===에서 산출
키워드가 도입된 이후 async/await
코드 구현이 훨씬 더 우아해졌습니다.
2. 인터페이스 라이브러리 wxPython
wxPython은 Python 프로그래밍 언어를 위한 크로스 플랫폼 GUI 툴킷 입니다. 이를 통해 Python 프로그래머는 강력하고 강력한 그래픽 사용자 인터페이스를 사용하여 프로그램을 간단하고 쉽게 만들 수 있습니다. 이는 C++로 작성된 인기 있는 wxWidgets 크로스 플랫폼 라이브러리의 GUI 구성 요소를 래핑하는 Python 확장 모듈 세트로 구현됩니다.
pip install wxpython
특히 windows
다음 독특하고 멋진 창 효과를 많이 얻을 수 있습니다. 자세한 내용은 wxDemo
예제를 실행하여 참조할 수 있습니다.
# 运行 python目录下/Scripts/wxdemo.exe
C:\ProgramData\Anaconda3\envs\ctrip_code36\Scripts>wxdemo.exe
![162dd50a9996c146ca9b33133844684a.png](https://img-blog.csdnimg.cn/img_convert/162dd50a9996c146ca9b33133844684a.png)
멀티태스킹 코루틴
1. 비동기 작업 생성
먼저 비동기 작업을 생성하고, 작업 기간을 무작위로 지정하고, 작업 시작 시간과 종료 시간을 기록합니다.
async def AsyncTask(self, name):
t = random.randint(1, 5)
self.log('Start %s: %.8f, duration %ds' % (name, time.time() - self.start, t))
await asyncio.sleep(t) # 模拟长时间后台操作
self.log('End %s: %.8f' % (name, time.time() - self.start))
return name
async
비동기 함수를 정의하는 키워드는 await
작업이 반환될 때까지 기다립니다. 여기서는 asyncio.sleep()
실제 작업을 시뮬레이션하는 데 사용됩니다 IO
.
비동기 작업이 끝난 후 트리거될 콜백 함수를 설정합니다.
def task_callback(self, task):
time.sleep(1)
self.log('Callback %s: %.8f' % (task.result(), time.time() - self.start))
2. 창 인터페이스 구축
비동기 작업을 트리거하는 버튼과 현재 작업 상태를 표시하는 정적 텍스트가 포함된 간단한 창을 그립니다.
class MyFrame(wx.Frame):
def __init__(
self, parent, ID, title, pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE
):
wx.Frame.__init__(self, parent, ID, title, pos, size, style)
panel = wx.Panel(self, -1)
self.start = time.time() # 记录初始时间戳
btn = wx.Button(panel, -1, "启动异步任务", size=(100, 30))
btn.SetPosition((20, 20))
txt = wx.StaticText(panel, -1, "任务未运行", (200, 40))
txt.SetPosition((30, 70))
self.txt = txt
self.Bind(wx.EVT_BUTTON, self.OnButton, btn)
self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
![3e23eee0462cf73c2bf2f551407c0a3b.png](https://img-blog.csdnimg.cn/img_convert/3e23eee0462cf73c2bf2f551407c0a3b.png)
3. 스레드 생성
이벤트 루프를 획득하고 asyncio
, 독립 스레드를 시작하고, 기본 인터페이스 이벤트를 격리합니다.
def OnButton(self, evt):
async_loop = asyncio.get_event_loop()
if not async_loop.is_running():
threading.Thread(target=self._asyncio_thread, args=(async_loop,)).start()
return
4. 메인 작업 생성
task1
독립적인 하위 작업과 동시 하위 작업 세트 task2
가 포함된 기본 작업을 설정합니다 task3
.
먼저 주요 작업이
Master task
시작됩니다.5초 하위 작업이 시작됩니다
task1
.task2
완료 후 5초 하위 작업 과 4초 하위 작업이 동시에 시작되고task3
콜백 함수가 설정되었습니다.그런 다음
task3
작업 시간이 짧고 먼저 완료되며 작업 콜백이 트리거됩니다.그런 다음
task2
완료되고 해당 콜백이 실행됩니다.마지막으로
Master task
종료합니다.
def _asyncio_thread(self, async_loop):
self.log('Start %s: %.8f' % ('Master task', time.time() - self.start))
asyncio.set_event_loop(async_loop)
print('异步单任务', 'task1')
task = asyncio.ensure_future(self.AsyncTask('task1'))
async_loop.run_until_complete(task)
print('异步多任务并发', 'task2', 'task3')
tasks = []
task = asyncio.ensure_future(self.AsyncTask('task2'))
task.add_done_callback(self.task_callback)
tasks.append(task) # 将多个任务对象装在到一个任务列表中
task = asyncio.ensure_future(self.AsyncTask('task3'))
task.add_done_callback(self.task_callback)
tasks.append(task)
async_loop.run_until_complete(asyncio.wait(tasks))
self.log('End %s: %.8f' % ('Master task', time.time() - self.start))
return
![694798e38abf429d5ff5dbb765816de4.png](https://img-blog.csdnimg.cn/img_convert/694798e38abf429d5ff5dbb765816de4.png)
프로세스를 요약하면 다음과 같습니다.
asyncio
이벤트 루프를 얻으세요async_loop = asyncio.get_event_loop()
;스레드를 실행하고
async_loop
이를 하위 스레드에 삽입합니다.하위 스레드에서 이벤트 루프를 설정하고 기본 인터페이스 이벤트 루프를 분리합니다.
asyncio.set_event_loop(async_loop);
asyncio.ensure_future
비동기 작업을 구성하는 데 사용됩니다 .콜백 기능 설정을 사용하세요
add_done_callback
.비동기 기능을 실행하는 데 사용됩니다
async_loop.run_until_complete
.
동시 멀티태스킹 코루틴
하위 작업 간에 종속성이 없으면 동시 실행을 사용하여 프로그램의 실행 효율성을 크게 향상시킬 수 있습니다.
![1d3575cf30a2a99b2ec1b2f85220de7c.png](https://img-blog.csdnimg.cn/img_convert/1d3575cf30a2a99b2ec1b2f85220de7c.png)
1. 여러 비동기 작업 만들기
def OnButton(self, evt):
async_loop = asyncio.get_event_loop()
if not async_loop.is_running():
t = threading.Thread(target=self._asyncio_thread, args=(async_loop,))
t.start()
for i in range(5):
asyncio.run_coroutine_threadsafe(self.AsyncTask('task%d' % i), async_loop)
2. 스레드 생성
def _asyncio_thread(self, async_loop):
asyncio.set_event_loop(async_loop)
async_loop.run_forever()
3. 이벤트 루프 종료
스레드 내의 스레드가 시작되므로 프로그램을 닫을 때 프로그램이 원활하게 종료되도록 해당 정리 작업을 수행해야 한다는 점은 주목할 가치 async_loop
가 run_forever()
있습니다 call_soon_threadsafe(async_loop.stop)
.
def OnCloseWindow(self, evt):
async_loop = asyncio.get_event_loop()
async_loop.call_soon_threadsafe(async_loop.stop)
self.Destroy()
![539d2ff42c6fbe9a1555ec34843bfbc1.png](https://img-blog.csdnimg.cn/img_convert/539d2ff42c6fbe9a1555ec34843bfbc1.png)
추가 읽기
더 자세한 내용은 기본 원칙부터 디자인 패턴까지 매우 자세히 설명되어 있는 "Async IO in Python: A Complete Walkthrough"를 참조하세요.
https://realpython.com/async-io-python/
소스코드 다운로드
이 문제의 전체 소스 코드는 공개 계정 "Deep Awakening"에서 찾을 수 있으며 백그라운드에서 "asyncio"라고 답하여 다운로드 링크를 얻을 수 있습니다.
추신: 늦은 밤에 코딩할 때 코더는 본질적으로 커피를 코드로 변환하는 생물입니다. 하지만 커피를 너무 많이 마시는 것은 몸이 견디지 못해서 최근에는 커피를 끊고 자몽차에 푹 빠져들게 되었습니다.
헝쇼우탕 허니자몽차 추천드려요 하나 사시면 하나 공짜로 드려요 한국것보다 맛이 좋아요 그런데 국산제품 지지합니다.