async/await 완전 이해

17147 단어 .NETC#초학자tech
이 글은 완전한 이해async/await를 목표로 설명한다.
완전히 이해하기 위해 일부는 부정확하게 표현될 수 있으니 양해해 주십시오.
(사실과 다른 내용이 분명히 포함되어 있다면 지적해 주십시오)
그나저나 C#의 문법 설명이지만 다른 언어의 기본적인 생각은 같아야 한다.예를 들어 자바스크립트라면 Task형을 Promise형으로 바꿔 읽으면 좋을 것 같다.

비동기식 및 Task


완전히 이해하기 위해서async/await는 비동기 처리의 처리 방법을 완전히 이해해야 한다.
원래 비동기 처리는 무엇입니까?이런 생각이 있는 사람은 불평을 하세요.완전히 이해한 전제에서 동기 처리와 비동기 처리의 차이를 설명하다.
비동기 처리는 여러 개의 임무를 동시에 병행 처리하기 위한 것이지만 실제로 코드를 쓰면 비동기 처리의 임무가 끝날 때까지 기다리는 경우가 압도적이다.
public int RunTaskA()
{
    RunTaskBAsync(); // 非同期に処理される
    // taskBが終わってから続きがしたい・・・
}
작업 BRunTaskBAsync가 비동기 처리일 경우 작업 B는 이렇게 끝날 때까지 계속 처리됩니다.
만약 퀘스트 A가 퀘스트 B의 완성을 기다리고 싶다면 이런 상태를 알고 싶을 것이다.
  • 정상 종료 여부
  • 이상 발생 여부 및 이상 종료
  • 중도 취소 여부
  • 또한 퀘스트 B에 반환 값이 있을 때 퀘스트 B가 완성된 후에도 이 값을 받아야 한다.
    이때 등장하는 것은 Task형이다.Task 대상은 이 상태와 되돌아오는 값을 알려 줍니다.
    public int RunTaskA()
    {
        Task taskB = RunTaskBAsync(); // Task型のオブジェクトを返す
        
        bool status1 = taskB.IsCompletedSuccessfully; // 正常終了したかどうか
        bool status2 = taskB.IsFaulted; // 例外が発生して異常終了したかどうか
        bool status3 = taskB.IsCanceled; // 処理が途中でキャンセルされたかどうか
        var returnValue = taskB.Result; // 戻り値(ある場合)
    }
    
    사실상 이렇게 상태 처리를 받은 코드를 강제로 쓰지 않는다.
    그렇다면 퀘스트 B가 완성된 후에 퀘스트 A의 계속을 위해 어떻게 기술해야 하나요?거기에 등장한 것은 async/await였다.

    await


    비동기 처리 작업이 완료될 때까지 기다립니다await.
    await RunTaskBAsync(); // タスクBに戻り値がない(void)場合
    
    var returnValue = await RunTaskBAsync(); // タスクBに戻り値がある場合
    
    임무 B가 정상적으로 끝난 후 되돌아오는 값을 사용하여 계속 처리할 때 다음과 같다.
    var result = await RunTaskBAsync();
    Console.WriteLine(result); // 続きの処理
    
    작업 B가 비정상적으로 종료되거나 취소되었을 때의 오류 처리 사용try/catch은 다음과 같다.
    try
    {
      await RunTaskBAsync();
    }
    catch (TaskCanceledException ex)
    {
      // キャンセルされた場合の例外処理
    }
    catch (Exception ex)
    {
      // 異常終了した場合の例外処理
    }
    
    또한awaitTask형에 사용한다.따라서 반드시 방법이 집행될 때await를 사용하지 않아도 되고 대기 시간을 늦출 수 있다.
    Task<int> taskB = RunTaskBAsync(); // awaitをつけていないのでTask<int>型を受け取る
    
    // 何か別の処理 (この間もタスクBは非同期で実行されている)
    
    int result = await taskB; // ここでタスクBの完了を待つ
    
    에 비동기 처리의 빈틈이 생겼다.

    async

    await 사용 시 아래 규칙에 따라 실시한다.
  • 방법에 부여async 키워드(문법)
  • 이용형Task을 귀환형[1][2](문법)으로
  • 반환 시: Task<戻り値の型>
  • 반환하지 않을 경우: Task
  • 방법명칭의 어미에 Async(추천)
  • 호출 측면을 파악하기 위해 비동기 처리
  • public async Task<int> RunTaskAAsync()
    {
      int result = await RunTaskBAsync();
      return result + 1; // taskBの戻り値を使った計算例
    }
    
    이 샘플 코드의 요점은'귀환형Task<int>형, 실제 귀환형int형'이다.실제로 async 키워드를 추가하면 반환값은 자동으로 Task형 패키지로 돌아간다.이렇게 되면 호출자는 Task형 대상을 사용하여 비동기 처리를 할 수도 있고 스스로 생성하지 않아도 Task형을 만들 수 있어 가볍다.
    다음 그림과 같이 위의 요점을 기준으로 작업 A-> 작업 B-> 작업 C의 비동기 호출을 수행합니다.
    public async Task<int> RunTaskAAsync()
    {
      var result = await RunTaskBAsync(); // taskBの完了を待つ
      return result + 1;
    }
    
    private async Task<int> RunTaskBAsync()
    {
      await RunTaskCAsync(); // taskCの完了を待つ
      return 1 + 2 + 3;
    }
    
    private async Task RunTaskCAsync()
    {
      await Task.Delay(500); // 0.5秒待機
    }
    

    여러 비동기식 프로세스 동시 처리


    예를 들어 때로는 임무 B와 임무 C를 동시에 처리하고 쌍방이 완성한 후에 임무 A의 계속을 처리하려고 한다.
    이 경우 사용Task.WhenAll.Task.WhenAll는 "여러 퀘스트가 모두 완성되었는지 확인할 수 있음Task"으로 되돌아왔다.Task형으로 가능await.
    public async Task<int> RunTaskAAsync()
    {
      Task<int> taskB = RunTaskBAsync();
      Task<int> taskC = RunTaskCAsync();
      
      int[] results = await Task.WhenAll(taskB, taskC); // 両方完了後、戻り値が配列として返る
      
      return results[0] + results[1]; // タスクBとタスクCの結果を加算
    }
    
    private async Task<int> RunTaskBAsync()
    {
      await Task.Delay(100); // 0.1秒待機
      return 1 + 2 + 3;
    }
    
    private async Task<int> RunTaskCAsync()
    {
      await Task.Delay(200); // 0.2秒待機
      return 4 + 5 + 6;
    }
    

    총결산


    완전히 이해했어.
    계속 썼어요.👉 [3]
    각주
    cf. Async/await를 완전히 이해한 다음에 조금 더 이해할게요.
    cf. ↩︎ neuecc-async의 함정 Part3, async void를 피해야 하는 100억 이유
    UI 작업async void 모드도 있지만 여기서는 터치할 필요가 없습니다.초보자는 개의치 마라.↩︎

    좋은 웹페이지 즐겨찾기