특정 키워드를 입력하여, 프로그램이 한 작업이 완료될 때까지 블로킹되지 않고 다른 작업을 계속할 수 있도록 한다.
비동기 프로그래밍은 주로 입출력 작업, 네트워크 호출, 데이터베이스 쿼리 등과 같이 시간이 오래 걸리는 작업에 유용하다.
- 응답성 향상: 긴 작업을 백그라운드에서 수행하므로 UI가 블로킹되지 않고 사용자와 상호작용할 수 있습니다.
- 자원 효율성: 동시에 여러 작업을 수행하여 자원을 효율적으로 활용할 수 있습니다.
- 성능 향상: 여러 작업을 병렬로 처리하면 전반적인 응용 프로그램 성능이 향상될 수 있습니다.
비동기 프로그래밍을 사용하면 장기 실행 작업을 백그라운드에서 비차단적으로 실행할 수 있다.
이렇게 함으로써 애플리케이션의 응답성과 성능을 향상시킬 수 있다.
이러한 비동기 프로그래밍의 주요 키워드는 다음과 같다.
async: async 키워드는 비동기 메서드를 정의할 때 사용. 이 키워드를 메서드 선언 앞에 붙이면 해당 메서드는 비동기적으로 실행될 수 있다.
await: await 키워드는 비동기 메서드 내에서 다른 비동기 메서드나 Task의 완료를 기다릴 때 사용된다. await 키워드 뒤에는 Task나Task<TResult>
를 반환하는 메서드가 위치하며, 해당 작업이 완료될 때까지 실행이 일시 중지된다.
Task: Task 클래스는 비동기 작업을 나타내는 데 사용된다. 비동기 메서드는 Task를 반환하며, Task는 비동기 작업의 수행 상태와 결과를 나타낸다.
Task<TResult>
:Task<TResult>
는 비동기 작업의 결과를 반환하는 데 사용된다. 반환되는 값의 유형을 지정할 수 있으며, 비동기 메서드가 TResult 유형의 값을 반환하도록 지정된 경우 사용된다.
Task-based Asynchronous Pattern (TAP): TAP은 비동기 프로그래밍의 디자인 패턴으로, Task를 사용하여 비동기 작업을 표현하고 관리하는 방식을 설명.
상단의 코드는 비동기 방식이 아닌 동기 방식으로 구현된 것이다.
Task가 끝날 때까지, 메인이 종료되면 안 된다.
즉, Wait를 통해서 작업을 대기시켜주어야 한다.
Task.Delay()는 비동기적으로 지정된 시간 동안 대기하는 기능을 제공하지만, Wait() 메서드로 인해 해당 시간 동안 작업이 차단된다.
따라서 Task.Delay()가 완료될 때까지 대기하고 다음 문장을 실행한다. 이는 동기적인 흐름과 유사한 동작을 한다.
단일 스레드 결과
상단의 로직은, Task<long>.Run()
을 사용하여 비동기 작업을 시작했지만, 실제로는 단일 스레드에서 실행하는 로직이다.
Task<long>.Run()
을 사용하여 비동기 작업을 생성하고 실행한다.
작업은 num 변수만큼의 반복문을 수행하며 sum에 값을 더한 다음, 최종적으로 sum 값을 반환한다.
반복문을 완수하는 데 걸린 최종 시간이다.
10개 다중 스레드 결과
Task.Run()을 사용하여 10개의 작업을 비동기적으로 실행.
작업은 각각의 스레드에서 병렬로 실행된다.
Task<long>[]
tasks 배열은 비동기 작업을 저장하고 작업 결과를 추적한다.
첫 번째 반복문에서는 Task<long>.Run()
을 사용하여 비동기 작업을 생성하고 실행.
각 작업은 주어진 num 변수만큼의 반복문을 수행하여 sum에 값을 더하고, 최종적으로 sum 값을 반환한다.
최종적으로 프로세스의 동작 시간이 훨씬 짧아진 것을 알 수 있다.
다만, 하드웨어에 따라서 한 번에 돌릴 수 있는 스레드의 양이 다르기 때문에, 무한정으로 스레드의 숫자를 늘리는 것은 좋지 않다.
Parallel은 .NET 프레임워크에서 제공하는 기능으로, 다중 스레드 프로그래밍을 단순화하고 병렬 작업을 수행하는 데 사용된다.
Parallel 클래스는 병렬 반복, 병렬 실행, 데이터 분할 등의 작업을 쉽게 처리할 수 있는 메서드와 기능을 제공한다.
Parallel.For
: 병렬 반복, 메서드를 사용하여 반복 작업을 병렬로 처리할 수 있다.
Parallel.Invoke
: 메서드를 사용하여 여러 메서드 또는 작업을 병렬로 실행할 수 있다.
Parallel LINQ
: 병렬 데이터 처리, LINQ (Language-Integrated Query) 쿼리 연산을 병렬로 처리할 수 있는 기능을 제공한다. 컬렉션에 대한 쿼리 연산을 병렬로 실행하여 성능을 향상시킬 수 있다.
Parallel.For()는 주어진 범위(from부터 to까지의 갯수)에 대해 동시에 여러 스레드에서 실행되는 작업을 수행한다.
각 스레드는 지정된 범위 내에서 개별적으로 작업을 수행하며, 람다식을 통해 정의된 Action을 실행한다.
10개의 스레드를 이용한 작업과 시간차이가 별로 나지 않는다.