(C# : Basic) 6. Async, Await

Posted by : at

Category : CSharp


static Task Test()
{
    Console.WriteLine("Start Test");
    Task t = TaskDelay(3000);
    return t;
}

static void Main(string[] args)
{
    Task t = Test();
    // t.Wait();        // Wait가 없을경우 비동기로 동작한다.
    // 참고로 비동기라고 꼭 멀티쓰레드는 아님(여기선 싱글쓰레드로 동작)

    Console.WriteLine("while start");
    while(true)
    {

    }
}
static void TestAsync()
{
    Console.WriteLine("Start TestAsync");
    Task t = TaskDelay(3000);
    t.Wait();                       // 여기서 Wait를 해도 될까?
    // 여기가 엄청오래 걸리는 함수였다면???
    Console.WriteLine("End TestAsync");
}

static void Main(string[] args)
{
    TestAsync();

    Console.WriteLine("while start");
    while(true)
    {

    }
}
static async void TestAsync()
{
    Console.WriteLine("Start TestAsync");
    Task t = TaskDelay(3000);
    await t;            // 대기 하기는 하는데 완료될경우 다음줄이 실행됨.

    // 보통은 이렇게 사용함.
    // await Task t = TaskDelay(3000);
    Console.WriteLine("End TestAsync");
}

static void Main(string[] args)
{
    TestAsync();

    Console.WriteLine("while start");
    while(true)
    {

    }
}

리턴을 받는것도 가능하다

static async Task<int> TestAsync()
{
    Console.WriteLine("Start TestAsync");
    await Task t = TaskDelay(3000);
    Console.WriteLine("End TestAsync");
    return 1;
}

static async Task Main(string[] args)
{
    int ret = await TestAsync();

    Console.WriteLine("while start");
    Console.WriteLine(ret);
    while(true)
    {

    }
}

이런식으로 활용이 가능하다

static async Task Main(string[] args)
{
    Task<int> t = TestAsync();

    // 다른일을 하다가...

    // 필요해지면 대기
    int ret = await t;

    Console.WriteLine("while start");
    Console.WriteLine(ret);
    while(true)
    {

    }
}

Example

using System;
using System.Threading.Tasks;

namespace AsyncBreakfast
{
    class Program
    {
        static void Main(string[] args)
        {
            // 이렇게 구현할 경우 순차적으로 실행이 된다.
            Coffee cup = PourCoffee();
            Console.WriteLine("coffee is ready");

            Egg eggs = FryEggs(2);
            Console.WriteLine("eggs are ready");

            Bacon bacon = FryBacon(3);
            Console.WriteLine("bacon is ready");

            Toast toast = ToastBread(2);
            ApplyButter(toast);
            ApplyJam(toast);
            Console.WriteLine("toast is ready");

            Juice oj = PourOJ();
            Console.WriteLine("oj is ready");
            Console.WriteLine("Breakfast is ready!");
        }

        /* 구현은 생략 */
}

async하게 구현해보자

// ??? 이것도 await만 썼다뿐이지 순차적으로 동작함
// 이렇게 구현하면 안된다.
static async Task Main(string[] args)
{
    Coffee cup = PourCoffee();
    Console.WriteLine("coffee is ready");

    Egg eggs = await FryEggsAsync(2);
    Console.WriteLine("eggs are ready");

    Bacon bacon = await FryBaconAsync(3);
    Console.WriteLine("bacon is ready");

    Toast toast = await ToastBreadAsync(2);
    ApplyButter(toast);
    ApplyJam(toast);
    Console.WriteLine("toast is ready");

    Juice oj = PourOJ();
    Console.WriteLine("oj is ready");
    Console.WriteLine("Breakfast is ready!");
}
Coffee cup = PourCoffee();
Console.WriteLine("coffee is ready");

// Egg, Bacon, Toast는 비동기로 시작
Task<Egg> eggsTask = FryEggsAsync(2);
Task<Bacon> baconTask = FryBaconAsync(3);
Task<Toast> toastTask = ToastBreadAsync(2);

// 대기는 toast를 먼저대기하고
Toast toast = await toastTask;
ApplyButter(toast);
ApplyJam(toast);
Console.WriteLine("toast is ready");
Juice oj = PourOJ();
Console.WriteLine("oj is ready");

// egg, bacon 순으로 대기
Egg eggs = await eggsTask;
Console.WriteLine("eggs are ready");
Bacon bacon = await baconTask;
Console.WriteLine("bacon is ready");

Console.WriteLine("Breakfast is ready!");

좀 더 개선해보자

static async Task Main(string[] args)
{
    Coffee cup = PourCoffee();
    Console.WriteLine("coffee is ready");

    var eggsTask = FryEggsAsync(2);
    var baconTask = FryBaconAsync(3);
    var toastTask = MakeToastWithButterAndJamAsync(2);

    var breakfastTasks = new List<Task> { eggsTask, baconTask, toastTask };
    while (breakfastTasks.Count > 0)
    {
        Task finishedTask = await Task.WhenAny(breakfastTasks);
        if (finishedTask == eggsTask)
        {
            Console.WriteLine("eggs are ready");
        }
        else if (finishedTask == baconTask)
        {
            Console.WriteLine("bacon is ready");
        }
        else if (finishedTask == toastTask)
        {
            Console.WriteLine("toast is ready");
        }
        breakfastTasks.Remove(finishedTask);
    }

    Juice oj = PourOJ();
    Console.WriteLine("oj is ready");
    Console.WriteLine("Breakfast is ready!");
}

About Taehyung Kim

안녕하세요? 8년차 현업 C++ 개발자 김태형이라고 합니다. 😁 C/C++을 사랑하며 다양한 사람과의 협업을 즐깁니다. ☕ 꾸준한 자기개발을 미덕이라 생각하며 노력중이며, 제가 얻은 지식을 홈페이지에 정리 중입니다. 좀 더 상세한 제 이력서 혹은 Private 프로젝트 접근 권한을 원하신다면 메일주세요. 😎

Star
Useful Links