Computer >> 컴퓨터 >  >> 프로그래밍 >> C#

C# async와 await 키워드를 활용한 비동기 프로그래밍 완벽 가이드

C# 비동기 프로그래밍이란?

C#의 비동기(Asynchronous) 프로그래밍은 작업이 차단되거나 접근이 지연되는 상황을 효율적으로 처리할 수 있는 방식입니다. 동기(Synchronous) 방식으로 처리하면 특정 작업이 차단되는 순간 애플리케이션 전체가 대기 상태에 빠지고, 소요 시간이 길어지며 심한 경우 프로그램이 멈춘 것처럼 보일 수 있습니다. 반면 비동기 방식을 사용하면 애플리케이션이 대기 중에도 다른 작업을 계속 수행할 수 있습니다.

async와 await 키워드

C#에서는 async와 await 두 가지 키워드를 사용해 비동기 프로그래밍을 구현합니다. 이 키워드들을 활용하면 .NET Framework 리소스나 .NET Core 등과 함께 손쉽게 작업할 수 있습니다. 그리고 async 키워드로 정의된 메서드를 '비동기 메서드(async method)'라고 부릅니다.

동기 처리의 문제점

GUI가 있는 애플리케이션을 예로 들어보겠습니다. 큐(queue)의 내용을 확인하고 처리되지 않은 작업이 있으면 해당 작업을 꺼내 먼저 처리합니다. 이때 코드가 동기적으로 실행되므로 미처리 작업이 완료될 때까지 다른 모든 작업은 대기하게 됩니다. 처리 시간이 예상보다 오래 걸리면 애플리케이션은 사용자에게 '응답 없음' 상태로 보이게 됩니다.

앞서 설명한 내용을 코드로 살펴보겠습니다.

private void OnRequestDownload(object sender, RoutedEventArgs e) {
    var req = HttpWebRequest.Create(_requestedUri);
    var res = req.GetResponse();
}

GetResponse() 호출이 완료될 때까지 현재 스레드가 차단됩니다. 따라서 네트워크 지연이 발생하면 UI 스레드까지 함께 멈춰버리는 문제가 생깁니다.

async와 await로 문제 해결하기

위와 같은 문제는 async와 await 키워드를 사용하면 간단히 해결할 수 있습니다.

private async void OnRequestDownload(object sender, RoutedEventArgs e) {
    var req = HttpWebRequest.Create(_requestedUri);
    var res = await req.GetResponseAsync();
}

메서드 선언부에 async를 붙이고, 시간이 오래 걸리는 작업 앞에 await를 추가하면 해당 작업이 완료될 때까지 기다리는 동안에도 UI 스레드는 차단되지 않고 다른 작업을 계속 처리할 수 있습니다. 여기서 GetResponse() 대신 비동기 버전인 GetResponseAsync()를 호출한다는 점에도 주목할 필요가 있습니다. await는 비동기 작업의 결과를 기다리면서 그동안 호출자에게 제어권을 반환하기 때문에, 애플리케이션은 끝까지 반응성을 유지할 수 있습니다.