Async 코드를 차단하지 마십시오.

3144 단어
UI 프로그램 예
아래의 코드를 참고하시오.이벤트를 클릭하면 REST 호출이 시작되고 결과가 TextBox에 표시됩니다.
public static async Task GetJsonAsync(Uri uri)
{
    using (var client = new HttpClient())
    {
        var jsonString = await client.GetStringAsync(uri);
        return JObject.Parse(jsonString);
    }
}

public void Buttion1_Click(...)
{
    var jsonTask = GetJsonAsync(...);
    textBox1.Text = jsonTask.Result;
}

GetJson 메서드는 실제 REST 요청을 실행하고 결과를 JSON 객체로 변환합니다.단추를 누르면 이벤트를 처리하고 GetJson 방법이 완성될 때까지 기다린 다음 결과를 표시합니다.이 코드는 사라진 자물쇠를 일으킬 것이다.
ASP.NET 예
다음은 매우 간단한 예이다.우리는 REST 요청을 실행하는 같은 라이브러리 방법을 가지고 있습니다. 단지 이번에는 ASP에 사용됩니다.NET 컨텍스트 환경:
public static async Task GetJsonAsync(Uri uri)
{
    using (var client = new HttpClient())
    {
        var jsonString = await client.GetStringAsync(uri);
        return JObject.Parse(jsonString);
    }
}

public class MyController : ApiController
{
    public string Get()
    {
        var jsonTask = GetJsonAsync(...);
        return jsonTask.Result.ToString();
    }
}

같은 이유로 이 코드도 사라질 수 있다.
무엇이 사라진 자물쇠를 만들었는가
첫 번째 예에서는 현재 컨텍스트가 UI 컨텍스트이고 두 번째 예에서는 현재 컨텍스트가 ASP입니다.NET 요청 상하문 (주의: 하나의 ASP.NET 요청은 특정한 라인에 연결되지 않지만 같은 요청은 같은 시간에 한 라인에서만 실행됩니다) 따라서 이것은 상기 예시 코드가 실행한 결과입니다.
  • 맨 윗부분의 방법은 GetJsonasync 방법(UI/ASP.NET 상하문에서)을 호출했다
  • GetJson Async 메서드는 HttpClient를 호출합니다.GetStringAsync에서 REST 요청을 시작합니다
  • .
  • GetStringAsync 메서드는 REST 요청이 아직 완료되지 않았음을 나타냅니다
  • .
  • 다음 GetJson Async 방법은 GetString Async가 되돌아오는 작업을 기다립니다.현재 컨텍스트가 캡처되어 GetStringAsync가 완료된 후 GetJsonAsync 메서드를 계속합니다.GetJsonasync에서 미완성 작업을 되돌려줍니다. 이 방법이 완성되지 않았음을 표시합니다.
  • 최상위 메서드는 GetJsonasync 메서드에서 반환된 Task를 동시에 차단합니다. 이는 현재 스레드 컨텍스트를 차단합니다
  • .
  • 최종적으로 REST 요청이 완료됩니다.그러면 GetStringAsync에서 반환한 작업이 완료됩니다
  • .
  • 이 때 GetJson Async의 후속 코드가 실행될 준비를 하고 현재 스레드 상하문이 계속 실행될 때까지 기다립니다
  • 이때 자물쇠가 사라집니다.최상위 방법은 현재 상하문을 막고 GetJson Async 방법이 완성되기를 기다렸지만, GetJson Async 방법은 현재 상하문이 사용할 수 있기를 기다리고 있습니다.

  • 잠금 해제 방지
    여기에는 두 가지 방법으로 자물쇠가 사라지는 것을 피할 수 있다.
  • 언제든지 async 방법에서ConfigureAwait(false)
  • 사용
  • Task 를 차단하지 않고 ASync
  • 를 언제든지 사용
    새로운 GetJson Async 메서드는 첫 번째 메서드에 대해 다음과 같이 표시됩니다.
    public static async Task GetJsonAsync(Uri uri)
    {
        using (var client = new HttpClient())
        {
            var jsonString = await client.GetStringAsync(uri).ConfigureAwait(false);
            return JObject.Parse(jsonString);
        }
    }
    

    GetJsonasync 메서드의 대기 동작을 수정합니다. 현재 위아래 문장에서 실행을 회복하지 않고 온라인 스레드에서 스레드를 잡아서 계속 실행합니다.이것은 GetJsonasync 방법이 현재 상하문 라인에 다시 들어가는 것을 피합니다.
    두 번째 방법에서는 최상위 방법이 다음과 같이 표시됩니다.
    public async void Button1_Click(...)
    {
        var json = await GetJsonAsync(...);
        textBox1.Text = json;
    }
    
    public class MyController : ApiController
    {
        public async Task Get()
        {
            var json = await GetJsonAsync(...);
            return json.ToString();
        }
    }
    

    이것은 최상위 방법의 대기 행위를 수정할 것입니다. 모든 대기는 비동기적으로 기다릴 것입니다
    참고 자료
    Best practice to call ConfigureAwait for all server-side code Don't Block on Async Code

    좋은 웹페이지 즐겨찾기