Visual Basic에서 비동기 호출과 이벤트 처리는 언어의 버전과 애플리케이션 유형에 따라 여러 가지 방법으로 구현됩니다. 일반적인 WinForms 애플리케이션에서 VB.NET의 이벤트 큐 처리(event queue)는 일반적으로 Application.DoEvents() 호출을 포함합니다. 이 메소드는 이벤트 처리기가 사용자 인터페이스(UI) 흐름을 차단하지 않고 다른 메시지를 처리할 수 있도록 "제어를 놓을" 수 있게 합니다:
While loading Application.DoEvents() 'UI가 사용자 작업에 반응하도록 허용 End While
.NET에서 VB.NET을 사용하여 비동기 작업을 수행하기 위한 방법으로는 다음이 있습니다:
BackgroundWorker — 긴 작업을 안전하게 UI 스레드와 상호 작용하여 별도의 스레드에서 수행할 수 있도록 하는 WinForms 구성 요소입니다.Async/Await 키워드 — .NET 4.5에 등장한 현대적인 비동기 시스템으로, 비동기 코드를 "동기 코드처럼" 작성할 수 있게 해줍니다:Public Async Function LoadDataAsync() As Task Dim result As String = Await GetWebDataAsync() TextBox1.Text = result End Function
차이점:
DoEvents는 단순히 UI 메시지 큐를 처리하며 새로운 스레드를 생성하지 않습니다.BackgroundWorker는 작업을 별도의 스레드로 이동하고, UI 스레드로 안전하게 돌아갈 수 있는 이벤트를 제공합니다.Async/Await는 비동기를 구현하면서 UI 스레드로의 제어 반환을 캡슐화합니다.파일을 디스크에서 로드하고 ProgressBar를 업데이트해야 할 때,
DoEvents를 루프 내에서 사용하는 위험성은 무엇입니까?
답변:
DoEvents는 일시적으로 다른 Windows 이벤트에 제어를 전달하지만 스레드를 해제하지 않습니다. 무거운 루프 내에서 이를 사용하는 경우(예: 큰 파일을 읽고 동시에 인터페이스를 업데이트할 때) 예상치 못한 버그가 발생할 수 있습니다: 사용자 이벤트 및 마우스 이벤트가 처리되어 처리 작업이 다시 시작되거나 애플리케이션이 "정지"될 수 있습니다. 무거운 로드가 예상될 경우 BackgroundWorker 또는 Task를 사용하는 것이 좋습니다.
잘못된 접근 예:
For i = 1 To 1000000 ProgressBar1.Value = i / 10000 Application.DoEvents() '주 스레드를 해제하지 않음! Next
이야기
DoEvents를 사용했습니다. 이로 인해 인터페이스가 "정지"되었고, 사용자가 "열기" 버튼을 다시 클릭하면 두 번째 파일 읽기 프로세스가 시작되어 첫 번째 프로세스와 섞이면서 데이터 왜곡과 애플리케이션 크래시가 발생했습니다.이야기
BackgroundWorker에 익숙하지 않아서 UI에서 그래프를 업데이트하기 위해 DoEvents를 루프 내에서 사용하기로 결정했습니다. 방대한 점 집합을 업데이트할 때 애플리케이션이 멈추고 결국 "크래시"되었습니다. 이는 Windows 메시지 큐의 오버플로우로 인해 발생했습니다.이야기
비동기 호출을 Async/Await를 통해 사용했지만, 긴 작업이 "즉시" UI 스레드에서 실행될 수 없다는 것을 인지하지 못했습니다. 결과적으로 인터페이스가 클릭 입력에 반응하지 않았고, 프로그래스 바는 업데이트되지 않았습니다. 왜냐하면 긴 메서드가 여전히 기본 스레드에서 실행되고 있었기 때문입니다.