이번 글에서는 C#의 비동기 프로그래밍에서 핵심적인 역할을 하는 Task와 Task<T>의 사용법, 그리고 비동기 스트림(Async Streams)에 대해 정리합니다. 비동기 프로그래밍의 원리를 이해하고 실제로 활용 가능한 코드를 작성할 수 있도록 예시를 제시하며 이해할 수 있도록 설명하려 합니다.
C# Task 및 Task<T> 그리고 비동기 스트림
비동기 프로그래밍은 동시에 여러 작업을 처리할 수 있는 프로그래밍 방법입니다. 즉, 작업이 끝나기를 기다리지 않고 다른 작업을 계속해서 진행할 수 있게 해 줍니다. 예를 들어, 파일을 다운로드하는 동안 UI가 응답하지 않는 문제를 해결하기 위해 비동기 프로그래밍을 사용합니다. 이렇게 하면 다운로드가 완료될 때까지 사용자가 다른 작업을 계속 진행할 수 있게 됩니다.
Task 및 Task<T>의 사용법
Task는 비동기 작업을 나타내는 객체입니다. 간단히 말해서, Task는 우리가 시작한 비동기 작업이 언제 끝날지 알려주는 일종의 약속(Promise)라고 생각할 수 있습니다. 비동기 작업이 끝나면 Task가 완료되었다고 알려주는 방식입니다.
Task<T>는 반환값이 있는 비동기 작업을 나타냅니다. 여기서 <T>는 반환값의 자료형을 의미합니다. 예를 들어, Task<int>는 정수를 반환하는 비동기 작업을 뜻합니다.
Task를 사용한 비동기 함수
아래는 Task를 사용하여 비동기 작업을 구현하는 예시입니다. 간단한 딜레이 작업을 비동기로 처리하고, 그 동안 다른 작업을 처리할 수 있는 모습을 보여줍니다.
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("작업 시작");
await DoSomethingAsync();
Console.WriteLine("작업 완료");
}
static async Task DoSomethingAsync()
{
Console.WriteLine("3초 기다리는 중...");
await Task.Delay(3000); // 3초 대기
Console.WriteLine("3초 기다림 완료");
}
}
위 코드에서 DoSomethingAsync 메서드는 3초 동안 기다리는 비동기 작업을 수행합니다. await 키워드는 Task가 완료될 때까지 기다린다는 의미입니다. 이렇게 await을 사용하면, 메서드의 나머지 부분이 Task가 완료된 후에 실행됩니다.
Task<T>를 사용하여 결과 반환하기
이번에는 Task<T>를 사용하여 비동기 작업이 결과를 반환하는 예제를 보겠습니다.
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("계산 시작");
int result = await CalculateSumAsync(5, 10);
Console.WriteLine($"계산 결과: {result}");
}
static async Task<int> CalculateSumAsync(int a, int b)
{
await Task.Delay(2000); // 2초 대기
return a + b;
}
}
위 예시에서,
- CalculateSumAsync 메서드는 2초 동안 기다린 후에 두 숫자의 합을 반환합니다.
- Tas<int>는 결과로 정수 타입의 값을 반환하는 비동기 작업을 의미합니다.
- await을 사용하여 해당 작업이 끝난 후 결과를 얻습니다.
비동기 스트림(Async Streams)
비동기 스트림은 C# 8.0부터 도입된 기능으로, 데이터를 **비동기로 하나씩 읽어올 수 있는 기능**을 제공합니다. 예를 들어, 서버에서 대량의 데이터를 스트리밍으로 받아야 할 때, 모든 데이터를 한 번에 받는 대신 데이터가 도착하는 대로 하나씩 처리할 수 있습니다.
비동기 스트림을 사용하기 위해서는 IAsyncEnumerable<T>와 await foreach를 사용합니다.
다음은 비동기 스트림을 사용하는 간단한 예시입니다. 1초마다 숫자를 하나씩 비동기로 출력하는 코드입니다.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
await foreach (var number in GenerateNumbersAsync())
{
Console.WriteLine($"받은 숫자: {number}");
}
}
static async IAsyncEnumerable<int> GenerateNumbersAsync()
{
for (int i = 1; i <= 5; i++)
{
await Task.Delay(1000); // 1초 대기
yield return i;
}
}
}
위 코드에서, GenerateNumbersAsync 메서드는 1초마다 숫자를 하나씩 생성하여 반환합니다. await foreach를 사용하여 비동기 스트림에서 데이터를 하나씩 받아올 수 있습니다. 이를 통해 대량의 데이터를 효율적으로 처리할 수 있습니다.
오늘은 Task와 Task<T>를 사용하여 비동기 작업을 처리하는 방법과 비동기 스트림을 통해 데이터를 비동기로 효율적으로 처리하는 방법에 대해 살펴봤습니다. 중요한 점은 비동기 프로그래밍을 사용하면 프로그램이 긴 시간 동안 대기 상태에 있을 때도 다른 작업을 계속해서 수행할 수 있다는 것입니다.
'프로그래밍 언어 > C#' 카테고리의 다른 글
IDisposable 인터페이스를 활용한 C# 메모리 누수 방지 실전 가이드 - C# 24 (0) | 2024.11.19 |
---|---|
C# 가비지 컬렉션 메모리 관리와 최적화 - C# 23 (0) | 2024.11.15 |
C# 비동기 프로그래밍 async와 await로 네트워크와 파일 작업 처리하기 - C# 21 (0) | 2024.11.13 |
C# 람다 표현식과 LINQ 활용 그리고 컬렉션 필터링과 코드 최적화 이해하기 - C# 20 (0) | 2024.11.12 |
C# LINQ 연산자를 활용한 데이터를 효율적으로 다루는 간결한 쿼리 예제와 활용법 - C# 19 (0) | 2024.11.11 |