C# Asynchronous Programming

비동기 프로그래밍 소개 (Introduction to Asynchronous Programming)

비동기 프로그래밍은 프로그램의 실행 흐름을 차단하지 않고, 시간이 오래 걸리는 작업을 동시에 처리할 수 있는 방법을 제공합니다. C#에서는 asyncawait 키워드를 사용하여 비동기 작업을 처리할 수 있습니다. 비동기 프로그래밍은 주로 I/O 작업, 웹 요청, 데이터베이스 쿼리 등 긴 작업에 적합합니다.

비동기 메서드 (Asynchronous Methods)

비동기 메서드는 async 키워드로 선언되며, 일반적으로 Task 또는 Task<T>를 반환합니다. await 키워드를 사용하여 비동기 작업의 완료를 기다릴 수 있습니다.

예제: 기본 비동기 메서드 (Basic Asynchronous Method)

using System;
using System.Threading.Tasks;

namespace AsyncExample
{
    class Program
    {
        static async Task Main(string[] args)
        {
            Console.WriteLine("Starting async operation...");
            await PerformAsyncOperation();
            Console.WriteLine("Async operation completed.");
        }

        static async Task PerformAsyncOperation()
        {
            // 비동기 작업 (Simulate an asynchronous operation)
            await Task.Delay(2000); // 2초 대기
            Console.WriteLine("Operation in progress...");
        }
    }
}

이 예제에서는 PerformAsyncOperation 메서드가 2초 동안 대기하는 비동기 작업을 시뮬레이션합니다. await Task.Delay(2000)은 2초 동안 비동기적으로 대기합니다.

비동기 메서드와 예외 처리 (Exception Handling in Asynchronous Methods)

비동기 메서드에서 예외가 발생하면 await를 사용하는 코드 블록에서 해당 예외를 처리할 수 있습니다.

예제: 비동기 메서드에서 예외 처리 (Exception Handling in Asynchronous Methods)

using System;
using System.Threading.Tasks;

namespace AsyncExample
{
    class Program
    {
        static async Task Main(string[] args)
        {
            try
            {
                await PerformAsyncOperationWithException();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Exception caught: {ex.Message}");
            }
        }

        static async Task PerformAsyncOperationWithException()
        {
            await Task.Delay(1000);
            throw new InvalidOperationException("Something went wrong during the async operation.");
        }
    }
}

이 예제에서는 PerformAsyncOperationWithException 메서드가 예외를 발생시키며, Main 메서드에서 await로 이 예외를 처리합니다.

비동기 작업의 병렬 처리 (Parallel Execution of Asynchronous Tasks)

여러 비동기 작업을 동시에 실행할 수 있습니다. 이는 Task.WhenAll 메서드를 사용하여 구현할 수 있습니다.

예제: 병렬 비동기 작업 (Parallel Asynchronous Tasks)

using System;
using System.Threading.Tasks;

namespace AsyncExample
{
    class Program
    {
        static async Task Main(string[] args)
        {
            Task task1 = Task1();
            Task task2 = Task2();

            await Task.WhenAll(task1, task2);

            Console.WriteLine("All tasks completed.");
        }

        static async Task Task1()
        {
            await Task.Delay(2000); // 2초 대기
            Console.WriteLine("Task 1 completed.");
        }

        static async Task Task2()
        {
            await Task.Delay(1000); // 1초 대기
            Console.WriteLine("Task 2 completed.");
        }
    }
}

이 예제에서는 Task1Task2를 동시에 실행하고, 두 작업이 모두 완료될 때까지 기다립니다. Task.WhenAll을 사용하여 병렬로 실행되는 작업을 처리합니다.

비동기 프로그래밍과 UI (Asynchronous Programming and UI)

UI 애플리케이션에서 비동기 작업을 사용하면 UI 스레드가 차단되지 않도록 할 수 있습니다. 이는 주로 WPF 또는 Windows Forms 애플리케이션에서 사용됩니다.

예제: 비동기 작업과 UI (Asynchronous Tasks and UI)

using System;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AsyncWinFormsExample
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private async void buttonStart_Click(object sender, EventArgs e)
        {
            buttonStart.Enabled = false;
            await LongRunningOperation();
            buttonStart.Enabled = true;
        }

        private async Task LongRunningOperation()
        {
            await Task.Delay(3000); // 3초 대기
            MessageBox.Show("Operation completed.");
        }
    }
}

이 예제에서는 버튼 클릭 시 비동기 작업을 수행하며, 작업이 완료된 후 버튼을 다시 활성화합니다. UI 스레드가 차단되지 않도록 비동기 작업을 사용합니다.

비동기 스트림 (Asynchronous Streams)

C# 8.0부터는 비동기 스트림을 지원합니다. IAsyncEnumerable<T>await foreach를 사용하여 비동기적으로 데이터를 스트리밍할 수 있습니다.

예제: 비동기 스트림 사용 (Using Asynchronous Streams)

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace AsyncStreamsExample
{
    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 = 0; i < 5; i++)
            {
                await Task.Delay(1000); // 1초 대기
                yield return i;
            }
        }
    }
}

이 예제에서는 GenerateNumbersAsync 메서드가 1초 간격으로 숫자를 생성하고, await foreach를 사용하여 비동기 스트림으로 데이터를 읽어옵니다.

비동기 프로그래밍 종합 예제 (Comprehensive Example of Asynchronous Programming)

using System;
using System.Net.Http;
using System.Threading.Tasks;

namespace AsyncExample
{
    class Program
    {
        static async Task Main(string[] args)
        {
            Console.WriteLine("Starting web request...");
            string result = await FetchWebContentAsync("https://www.example.com");
            Console.WriteLine("Web request completed.");
            Console.WriteLine($"Content length: {result.Length} characters");
        }

        static async Task<string> FetchWebContentAsync(string url)
        {
            using (HttpClient client = new HttpClient())
            {
                string content = await client.GetStringAsync(url);
                return content;
            }
        }
    }
}

이 종합 예제에서는 FetchWebContentAsync 메서드를 사용하여 비동기적으로 웹 페이지의 내용을 가져오고, 내용을 콘솔에 출력합니다. HttpClient를 사용하여 비동기 HTTP 요청을 수행합니다.

결론 (Conclusion)

비동기 프로그래밍은 현대 애플리케이션에서 중요한 부분을 차지하며, C#에서는 asyncawait 키워드를 통해 비동기 작업을 쉽게 처리할 수 있습니다. 비동기 작업을 통해 UI 스레드를 차단하지 않고, 효율적으로 긴 작업을 처리하며, 다양한 비동기 연산자와 패턴을 활용할 수 있습니다. 비동기 스트림과 같은 최신 기능을 사용하여 데이터 스트리밍을 비동기적으로 처리하는 것도 가능합니다.

Posted in C#

Leave a Reply

Your email address will not be published. Required fields are marked *