비동기식 C#: 위쪽 체리🍒 (힌트와 팁)

11452 단어 dotnetcsharpwebdev
이 시리즈에서 우리는 아주 좋은 시도를 하여 C#로 효율적인 비동기 코드를 쓰기 시작했다. 나는 몇 가지 기교와 기교로 이 시리즈를 완성하고 싶다. 이런 기교와 기교는 대부분의 개발 사례에서 반드시 도움이 될 것이다.
안전벨트를 매다🚀..

✔ 힌트 1
static async Task BoilWaterAsync()
{
    Console.WriteLine("Starting the kettle");
    await Task.Delay(3000);
    Console.WriteLine("Kettle Finished Boiling");
}

static async Task PourWaterAsync()
{
    var boilWaterTask = BoilWaterAsync();
    await boilWaterTask;
    Console.WriteLine("Pouring boiling water.");
}

static async Task Main(string[] args)
{
    // Notice we are not awaiting the task!
    PourWaterAsync();
    Console.WriteLine("Program Ended");
}

우리의 첫 번째 예에서 PourWaterAsync()Task 기다리지 않은 임무를 나타낸다. 비록 이 임무는 기다리고 있는 내부 임무로 구성되어 있지만.
이 예제를 실행하면 다음과 같은 출력이 발생합니다.
Starting the kettle
Program Ended
임무Task.Delay(3000)가 시작되었지만 기다림에도 불구하고 종점선에 도착하지 않았고 주전자도 끓지 않았다.
이 동작은 최고급 await 함수에서 Main() 키워드를 건너뛰었기 때문에 발생합니다.
물론 이 두 줄을 다시 써라.
var boilWaterTask = BoilWaterAsync();
await boilWaterTask;
다음이 됩니다.
await BoilWaterAsync();
같은 결과를 얻게 될 것이다.
마지막 호출점에 도착할 때까지 모든 작업을 기다립니다.

✔ 힌트
public void Main(string[]args)
{
    var task = BoilWaterAsync();

    // DON'T
    var result = task.Result;

    // A NO-NO
    task.Wait();

    // PLEASE DON'T ⛔
    task.GetAwaiter().GetResult();
}


상기 세 가지 주의사항은 프로그램의 주 라인이 막힐 것입니다. 작업이 끝날 때까지 프로그램은 새로운 요청에 대한 응답을 멈추거나 동기화가 끝날 때까지 기다릴 수 있습니다.
✅ 만들다
작업의 비동기성을 받아들이고 결과를 되돌려줍니다.코드에서 전파되는 임무는 정상적인 것이기 때문에 가능한 한 늦추면 된다.

✔ 프롬프트 #3
만약 우리가 인터페이스를 실현하고 있다면, 그 방법은 임무를 되돌려야 하지만, 이 방법 자체의 실행은 비동기적인 설정이 필요하지 않고, 주 라인을 막지 않으며, 동시에 실행할 수 있어 문제가 발생하지 않을 것이다.
interface MyInterface
{
    Task<string> DoSomethingAndReturnAString();
}

class MyClass : MyInterface
{
    public Task<string> DoSomethingAndReturnAString()
    {
        // Some logic that does not need the await keyword
        return "result"; // Of course a compiler error, expecting Task<string> not a string
    }
}
우리는 두 가지 방법으로 이 문제를 해결할 수 있다.

솔루션 1 (최악)👎):
방법을 async (우리가 아무것도 기다릴 필요가 없어도) 로 바꾸면 문자열을 정상적으로 되돌릴 수 있습니다. 그렇습니까?영원히 그렇게 하지 마!
방법을 async 로 표시할 때, 컴파일러는 코드를 상태기로 변환합니다. 예를 들어 대기할 때 실행되고, 백엔드 작업이 끝난 후에 실행을 재개하는 등 몇 가지 일을 추적합니다.실제로, 방법을 async 로 표시한 후에 코드가 생성한 IL (중간 언어) 을 검사하면, 이 함수가 완전한 클래스가 되었다는 것을 알 수 있습니다.
따라서 async(내부 대기 없음)로 표시된 동기화 방법에서도 상태기는 어떤 방식으로든 생성되며 더 빠른 속도로 내연되고 실행될 수 있는 코드는 상태기 관리에 추가적인 복잡성을 가져올 수 있다.
📝 이것이 바로 내부에wait만 존재할 때 방법을 비동기적으로 표시하는 것이 매우 중요한 이유이다.

솔루션 2(우수👍):
대신: return Task.FromResult("result");다시 한 번 예를 들자.
외부 네트워크 소스에서 일부 텍스트를 검색하는 HTTP 클라이언트가 있습니다.
public Task<string> GetFromWebsite()
{
    var client = new HttpClient();
    var content = client.GetStringAsync("my.website.com");

    •••
}
만약 목표가 웹 사이트에서 문자열을 검색하기 시작했을 뿐이라면 가장 좋은 방법은 원래 상태로 되돌아오는 GetStringAsync() 작업입니다. 여기서 기다리지 마십시오. 이것은 목적 없이 상태기를 만드는 것을 건너뛰는 것과 같은 원인으로 귀결됩니다.
public Task<string> GetFromWebsite()
{
    var client = new HttpClient();
    return client.GetStringAsync("my.website.com");
}
호출을 기다리려는 유일한 시나리오는 메소드 내의 결과에 대해 로직을 수행하려는 것입니다.
// Notice that we marked the method as async
public async Task<string> GetFromWebsiteAndValidate()
{
    var client = new HttpClient();
    var result = await client.GetStringAsync("my.website.com");

    // Perform some logic on the result

    return result;
}
만약 당신이 방법의 기능을 묘사할 때 'and' 라는 단어를 사용한다면, 어떤 부분은 옳지 않을 수도 있다는 것을 기억해라.
예:
  • "내 방법은 x, y,z를 만드는 거야"(아니야, 아니야.⛔)
  • "나는 세 가지 방법이 있는데, 하나는 x에 쓰고, 다른 하나는 y에 쓰고, 마지막은 z에 쓴다."(네)✔)
  • 이것은 코드 응용 단위 테스트를 시도할 때의 생활을 더욱 수월하게 할 것이다.
    이것은 경험의 법칙이다👍 참고:
    임무의 결과가 절대적으로 필요할 때만 기다린다.
    async 키워드는 서로 다른 라인에서 이 방법을 실행하지 않으며, 다른 종류의 숨겨진 마법도 실행하지 않기 때문에, 방법에서 키워드wait를 사용해야 할 때만 이 방법을 async로 표시합니다.
    기억해야 할 몇 가지 주의 사항:
  • 비동기 함수는 세 가지 유형 중 임의의 하나를 되돌릴 수 있다. void, Task 또는 Task<T>.
  • 함수는'기다릴 수 있는'이다. 함수는 Task 또는 하나Task<T>로 되돌아오는 것이지 async로 표시되기 때문에 우리는 await 비동기적인 함수Task를 되돌아갈 수 있다.
  • 함수await를 되돌릴 수 없습니다. void 함수는 되돌려 주지 않을 절대적인 이유가 없거나Task 함수 호출자가 무효 형식을 되돌려 주기를 원하지 않거나 함수 자체가 최고급 함수이기 때문에 다른 함수는 호출할 수 없습니다.

  • ✔ 힌트
    긴 시간 동안 실행되는 작업은 항상 비동기적으로 실행되어야 하며, 이러한 작업은 입출력 제한과 CPU 제한의 두 종류로 나눌 수 있습니다.입출력 작업이 완료될 때까지 대기하는 데 걸리는 시간에 따라 작업이 완료되는 데 걸리는 시간이 주로 달라질 때 작업을 입출력 제한이라고 합니다.이에 비해 CPU 제한 작업의 완료 시간은 주로 중앙 프로세서의 속도에 따라 달라집니다. 예를 들어 다음과 같습니다.
  • 입출력 바인딩 작업:
  • 네트워크에서 데이터 요청
  • 데이터베이스 액세스
  • 파일 시스템 읽기/쓰기
  • CPU 제한 작업: 일반적으로 다음과 같은 값비싼 계산을 수행합니다.
  • 그래픽 렌더링
  • 비디오 압축
  • 복잡한 수학 계산
  • 보통 입출력 바인딩Task이나 Task<T>이 있을 때awaitasync 방법으로 바인딩합니다.CPU가 바인딩된 코드의 경우 백그라운드 스레드 Task.Run 방법을 사용하여 시작할 때까지 기다려야 합니다.
    메모📝:
    CPU 바인딩 코드의 실행 상황을 분석하고 다중 스레드 처리 시 상하문 전환 비용을 주의해야 합니다. 비교적 비싸지 않을 수도 있습니다.
    자, 이것이 바로 내가 오늘 너희들에게 줄 것이다.
    계속 인코딩😉

    좋은 웹페이지 즐겨찾기