본문 바로가기

C#

C# asyn, await

반응형
  • 메서드에 async(비동기 메서드)와 await(실행 완료까지 대기)가 한 쌍으로 사용함(아주 가끔 await를 안쓰기도 함)
  • 비동기 메서드의 반환 값은 Task, Task<T> 형태임

Main 메서드를 비동기로하여 async와 await 키워드 사용

public class AsyncAwaitTest
{
    public string Name { get; set; }
    public int DelayValue { get; set; }

    public AsyncAwaitTest(string name, int delayValue){ Name = name; DelayValue = delayValue; }

    public async Task<int> DownloadPageAsync()
    {
        await StartAsync();

        var client = new HttpClient();
        byte[] content = await client.GetByteArrayAsync("https://docs.microsoft.com/en-us/");
        await Task.Run(async () =>
        {
            await Task.Delay(DelayValue);
            Console.WriteLine($"{Name}, 다운로드 완료");
        });

        return content.Length;
    }

    private async Task StartAsync()
    {
        await Task.Delay(DelayValue);
        Console.WriteLine($"{Name}, 다운로드 시작");
    }
}

 

class Program
{
    // Main 메서드를 async 키워드를 붙여 비동기 메서드로 변경
    static async Task Main(string[] args)
    {
        AsyncAwaitTest testA = new AsyncAwaitTest("A", 1000);
        AsyncAwaitTest testB = new AsyncAwaitTest("B", 1);
        var taskA = await testA.DownloadPageAsync();
        var taskB = await testB.DownloadPageAsync();

        Console.WriteLine($"테스트 종료, A결과: {taskA}, B결과: {taskB}");
        // 비동기 실행중인데 메인이 종료되는 것을 막기 위해
        Console.ReadLine();
    }
}

 


동기 메서드에서 Task.Run() 메서드를 사용하여 비동기 메서드 호출

class Program
{
    static void Main(string[] args)
    {
        int taskA = 0;
        int taskB = 0;
        Task.Run(async () =>
        {
            AsyncAwaitTest testA = new AsyncAwaitTest("A", 1000);
            taskA = await testA.DownloadPageAsync();
            Console.WriteLine($"A결과: {taskA}");
            
            AsyncAwaitTest testB = new AsyncAwaitTest("B", 1);
            taskB = await testB.DownloadPageAsync();
            Console.WriteLine($"B결과: {taskB}");
        });

        Console.WriteLine($"테스트 종료");
        Console.ReadLine();
    }
}

 

class Program
{
    static void Main(string[] args)
    {
        int taskA = 0;
        int taskB = 0;
        Task.Run(async () =>
        {
            AsyncAwaitTest testA = new AsyncAwaitTest("A", 1000);
            taskA = await testA.DownloadPageAsync();
            Console.WriteLine($"A결과: {taskA}");
        });

        Task.Run(async () =>
        {
            AsyncAwaitTest testB = new AsyncAwaitTest("B", 1);
            taskB = await testB.DownloadPageAsync();
            Console.WriteLine($"B결과: {taskB}");
        });

        Console.WriteLine($"테스트 종료");
        Console.ReadLine();
    }
}

 

Task.Delay값을 둘다 1로 줬을 때 결과

AsyncAwaitTest testA = new AsyncAwaitTest("A", 1);
AsyncAwaitTest testB = new AsyncAwaitTest("B", 1);

 


Task.WhenAll() 메서드 사용하여 모든 작업이 완료될 때까지 대기

class Program
{
    static void Main(string[] args)
    {
        Task.Run(async () =>
        {
            AsyncAwaitTest testA = new AsyncAwaitTest("A", 1000);
            AsyncAwaitTest testB = new AsyncAwaitTest("B", 1000);
            AsyncAwaitTest testC = new AsyncAwaitTest("C", 1000);

            Task<int> taskA = testA.DownloadPageAsync();
            var taskB = testB.DownloadPageAsync();

            await Task.WhenAll(taskA, taskB, testC.DownloadPageAsync());

            Console.WriteLine("모든 작업 완료");
        });

        Console.WriteLine($"테스트 종료");
        Console.ReadLine();
    }
}

 


Task.WhenAny() 메서드 사용하여 작업 하나씩 완료 확인

class Program
{
    static void Main(string[] args)
    {
        Task.Run(async () =>
        {
            AsyncAwaitTest testA = new AsyncAwaitTest("A", 1000);
            AsyncAwaitTest testB = new AsyncAwaitTest("B", 1000);
            AsyncAwaitTest testC = new AsyncAwaitTest("C", 1000);

            var taskA = testA.DownloadPageAsync();
            var taskB = testB.DownloadPageAsync();
            var taskC = testC.DownloadPageAsync();

            List<Task> tasks = new List<Task>() { taskA, taskB, taskC };
            // 작업이 하나라도 있으면 실행
            while (tasks.Any())
            {
                Task task = await Task.WhenAny(tasks);
                if (task == taskA)
                {
                    int i = await taskA;
                    Console.WriteLine($"A 완료, i: {i}");
                }
                else if (task == taskB)
                {
                    int i = await taskB;
                    Console.WriteLine($"B 완료, i: {i}");
                }
                else if (task == taskC)
                {
                    int i = await taskC;
                    Console.WriteLine($"C 완료, i: {i}");
                }
                // 완료된 작업 리스트에서 삭제
                tasks.Remove(task);
            }

            Console.WriteLine("모든 작업 완료");
        });

        Console.WriteLine($"테스트 종료");
        Console.ReadLine();
    }
}

반응형

'C#' 카테고리의 다른 글

C# 튜플(Tuple)  (0) 2022.01.02
C# 리플렉션(reflection)  (0) 2021.12.30
C# 확장 메서드  (0) 2021.12.27
C# 이벤트(Event)  (0) 2021.12.26
C# 대리자(Delegate), 무명 메서드, 람다식  (0) 2021.12.26