C# - 비동기 프로그래밍(async, await) - 개념, 사용 방법, 비동기식 병렬 처리

반응형

 

동기식 vs 비동기식

  동기식 비동기식
작업 처리 순차적 처리,
하나의 작업이 끝나야 다음 작업 시작
동시 처리,
한 작업이 완료되기 전에 다음 작업 수행
장점 순차적으로 실행되기 때문에 간단하고 직관적인 코드 작성 가능 동시에 실행되기 때문에 다른 작업을 기다리지 않고 빠른 처리 가능
단점 한 작업이 오래 걸리면 다음 작업 수행을 위한 대기 시간이 존재하므로 작업 속도 저하 가능성 존재 코드 복잡도 증가,
작업간의 순서나 종속성 관리의 어려움
사용 예시 간단한 작업,
UI 업데이트와 같이 즉각적인 반응이 필요한 작업
파일을 읽고 쓰는 작업,
데이터 베이스 연결과 같이 시간이 오래 걸리는 작업

비동기 프로그래밍

  • C#에서는 콜백을 조작하거나 비동기를 지원하는 라이브러리가 필요하지 않음
  • 내장된 비동기 모델을 사용하여 비동기 코드를 쉽게 작성 할 수 있음

비동기 모델

  • 백그라운드에서 수행
  • 백그라운드에서 수행되는 작업을 모델링하는 데 사용되는 구문 Task<> 및 Task사용
    • Task(또는 Task<T>) : 비동기 작업 모델링 하는 개체
  • async 키워드는 본문에서 await 키워드를 사용할 수 있는 비동기 메서드로 변환
    • async 및 await : 비동기 모델을 조작하는 키워드
  • await 키워드는 비동기 메서드 내부에서만 사용 가능

동기/비동기 작업 절차

  • 동기식의 경우
    1. 하나의 작업 수행
    2. 다음 작업은 수행중인 작업이 끝날 때까지 대기
    3. 작업이 끝나면 다음 작업 수행
    4. 반복
  • 비동기식의 경우
    1. 하나의 작업 수행
    2. 다음 작업 수행
    3. 각각의 작업 수행 종료

UI 프로그램에서의 비동기 프로그래밍

  • 동기 : 작업이 수행되면 UI 쓰레드가 정지 됨
  • 비동기 : 작업이 수행되어도 UI 쓰레드가 정지되지 않음
    • 예) 버튼을 누르면 1초 뒤 레이블에 텍스트가 입력되는 간단한 프로그램
private void btn_sync_Click(object sender, EventArgs e)
{
    Thread.Sleep(1000);
    label1.Text = "동기식";
}

private async void btn_async_Click(object sender, EventArgs e)
{
    await Task.Delay(1000);
    label1.Text = "비동기식";
}

  • 동기식의 경우 1초동안 UI 쓰레드가 정지되기 때문에 창을 이동하거나 다른 작업을 수행 할 수 없음
  • 비동기식의 경우 UI 쓰레드와 별개로 작업을 수행하기 때문에 창 이동과 다른 작업을 수행 할 수 있음

비동기의 병렬 처리

  • 비동기를 병렬로 작업을 수행하게 프로그래밍하여 여러 작업을 동시에 수행 할 수 있음
  • 그러나 작업간의 순서 또한 잘못될 수 있으므로 주의하여야 함
    • 예) 버튼을 누르면 "2", "3" 각각의 숫자가 2초, 3초 뒤에 입력되는 프로그램
private void btn_sync_method_Click(object sender, EventArgs e)
{
	// 동기 처리
    syncTest();
}

private void btn_async_method_Click(object sender, EventArgs e)
{
	// 비동기 처리
    asyncTest();
}

private void syncTest()
{
    string txt;

    // 1 입력
    txt = "1";

    // 2초 뒤 2 입력
    Thread.Sleep(2000);
    txt += "2";

    // 1초 뒤 3 입력
    Thread.Sleep(1000);
    txt += "3";

    label1.Text = txt;
}

private async void asyncTest()
{
    string txt;

    // 1 입력
    txt = "1";

    // 2초 뒤 2 입력
    Task t1 = Task.Run(() =>
    {
        Task.Delay(2000);
        txt += "2";
    });

    // 1초 뒤 3 입력
    Task t2 = Task.Run(() =>
    {
        Task.Delay(1000);
        txt += "3";
    });

    await Task.WhenAll(t1, t2);

    label1.Text = txt;
}

 

  • 비동기 메서드의 경우
  • 2 입력(2초), 3 입력(1초)을 동시에 수행하기 때문에 "132"의 값이 출력
  • 또한, 작업 수행동안 프로그램의 이동이나 다른 작업을 수행할 수 있음

 

  • 동기 메서드의 경우
  • 차례로 2입력(2초) 후 3입력(3초)를 수행하기 때문에 "123"의 값이 출력
  • 작업을 수행하는 동안 프로그램을 이동하거나 다른 작업을 수행할 수 없음


참고

Microsoft - Learn - .NET - C# 가이드 - 비동기 프로그래밍

CsharpStudy.com - C# 문법 - await

반응형