[C#] C# 코딩공부 #5 async / await 키워드

개발Velog·2020년 2월 2일
1

C#

목록 보기
5/9

async / await 이란?

C# 5.0부터 새로운 c# 키워드로 추가된 asyncawait는 비동기 프로그래밍을 보다 손쉽게 지원하기 위해 만들어졌다.

C# async는 컴파일러에게 해당 메서드에 await를 가지고 있음을 알려주는 역활을 한다.
async를 표시한다고 해서 자동으로 비동기 방식으로 프로그램을 수행하는 것은 아니고, 일종의 보조 역활을 하는 컴파일러 지시어라고 보면 된다.

실제 핵심 키워드는 await인데 일반적으로 Task 혹은 Task배열 객체와 함꼐 사용된다.
awaitbale 클래스, 즉 GetAwaiter()라는 메서드를 가진 클래스면 함께 사용이 가능하다.

await는 Task와 같은 awaitable 클래스의 객체가 완료되길 기다린다.
중요한 점은 UI 쓰레드가 정지되지 않고 메시지 루프를 계속 돌 수 있도록 필요한 코드를 컴파일러가 await키워드를 만나면 자동으로 추가된다.

예제 소스 1 - Background Thread에서 비동기 Task가 끝난 후, await가 다시 Caller가 갖고 있던 쓰레드 즉 UI Thread로 다음 문장들을 실행 하는 것 확인.

public Form1()
{
    InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
    Run();
}

private async void Run()
{
    // 비동기로 Worker Thread에서 도는 task1
    // Task.Run(): .NET Framework 4.5+
    var taks1 = Task.Run(() => LongCalcAsync(10));

    // task1이 끝나길 기다렸다가 끝나면 결과치를 sum에 할당
    int sum = await taks1;

    // UI Thread 에서 실행
    // Control.Invoke 혹은 Control.BeginInvoke 필요없음
    this.label1.Text = $"Sum = {sum}";//문자열 보간
}

private int LongCalcAsync(int times)
{
    int result = 0;
    for (int i = 0; i < times; i++)
    {
        result = result + 1;
        Thread.Sleep(1000);
    }

    return result;
}

예제 소스 2 - .NET 4.5 Aasync 혹은 TaskAsync 메서드 구분 추가


System.IO.Stream.Read() : 기존 동기 메서드
System.IO.Stream.ReadAsync() : 4.5 Async 메서드

WebClient.DownloadStringAsync() : 기존 비동기 메서드
WebClient.DownloadStringTaskAsync() : 4.5 TaskAsync 메서

예제 소스 3- UI 쓰레드에서 실행되는 예


private void button1_Click(object sender, EventArgs e)
{
    Run();
}

private async void Run()
{
    int sum = await LongCalc2(10);
    label1.Text = $"sum = {sum}"; 
    this.button1.Enabled = true;
}


private async Task<int> LongCalc2(int times)
{
    //UI Thread에서 실행
    Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);

    int result = 0;
    for (int i = 0; i < times; i++)
    {
        result += 1;
        await Task.Delay(1000);
    }

    return result;
}

예제 소스 4- Task.ContinueWith()

.Net 4.0 Task의 클래스의 ContinueWith()를 써서 구현 가능. 개념적으로 동일한 방식
아래 예제에서 .ContinueWith() 메서드는 첫번째 파라미터에서 task1 끝난 후 실행될 명령어들을 람다식으로 지정.
두번쨰 파라미터에는 실행블럭이 현재 쓰레드 (예제의 경우 UI Thread)에서 실행하도록 TaskScheduler.FromCurrentSynchronizationContext()를 지정.
즉 개념적으로 await는 특정 Task가 실행된 후 여러한 실행블럭을 현재 실행 컨텍스트에서 실행하도록 하는 것.


 var task1 = Task<int>.Run(() => LongCalc2(10));

// await task1과 동일한 효과
//
task1.ContinueWith(x => {
    this.label1.Text = "Sum = " + task1.Result;
    this.button1.Enabled = true;
}, TaskScheduler.FromCurrentSynchronizationContext());

##### 출처 및 참조 :  http://www.csharpstudy.com/
profile
안녕하세요. 데이터와 동고동락 중인 개발자 입니다.

0개의 댓글