단일 방법 내에서 동기화 및 비동기 방법의 효율적인 혼합?


11

좋아, 이상하게 들리지만 코드는 매우 간단하고 상황을 잘 설명합니다.

public virtual async Task RemoveFromRoleAsync(AzureTableUser user, string role)
{
    AssertNotDisposed();
    var roles = await GetRolesForUser(user);
    roles.Roles = RemoveRoles(roles.Roles, role);
    await Run(TableOperation.Replace(roles));
}

(저는 초록에서 일종의 이야기를하고 있지만 위의 내용은 실제로 여기에서 요구하는 것을 실제로 수행하는 실제 생산 코드의 실제 방법이며 실제로는 귀하의 실제 검토에 관심이 있습니다 정확성을 위해 async / await 패턴을 사용하십시오.)

나는 async/ await더 많이 사용하기 때문에이 패턴이 점점 더 자주 발생합니다 . 패턴은 다음과 같은 일련의 이벤트로 구성됩니다.

  1. 내가 작업해야 할 정보를 얻는 최초의 전화를 기다립니다
  2. 해당 정보에 대해 동 기적으로 작업
  3. 업데이트 된 작업을 저장하는 최종 통화를 기다립니다

위의 코드 블록은 일반적으로 이러한 메소드를 처리하는 방법입니다. 나는 await내가 비동기이기 때문에해야하는 첫 번째 호출. 다음으로 IO 또는 리소스 바운드가 아닌 비동기 작업이 필요한 작업을 수행합니다. 마지막으로, 나는 또한 async호출 인 나의 일을 저장 하고,화물 컬트에서 벗어납니다 await.

그러나 이것이이 패턴을 처리하는 가장 효율적이고 올바른 방법입니까? await마지막 전화를 건너 뛸 수있는 것처럼 보이지만 실패하면 어떻게됩니까? 그리고 동기 작업을 원래 호출과 연결 Task하는 것과 같은 방법을 사용해야 ContinueWith합니까? 나는 이것을 올바르게 처리하고 있는지 확실하지 않은 시점에 있습니다.

예제에 코드가 주어지면 이 async / sync / async 메서드 호출 체인을 처리하는 더 좋은 방법이 있습니까?


코드는 가능한 짧고 이해하기 쉽습니다. 내가 생각할 수있는 것은 불필요한 복잡성을 초래합니다.
Euphoric

@ 유포 릭 : 마지막 전화를 기다리고 귀찮게해야합니까? 내가하지 않으면 어떻게됩니까? 현재와 ​​다른 것이 있습니까?
바가지

답변:


3

예, 이것이 올바른 방법이라고 생각합니다.

두 번째는 건너 뛸 수 없습니다 await. 그렇게하면 방법이 너무 빨리 완료된 것처럼 보이며 (제거가 실제로 완료되기 전에) 제거가 실패했는지는 알 수 없습니다.

나는 ContinueWith()여기서 어떻게 도움 이 될지 모르겠다. 를 사용하지 않기 위해 사용할 수는 await있지만 코드가 더 복잡하고 읽기 어려워집니다. 그리고 이것이 핵심입니다 await. 연속을 사용하는 것과 비교할 때 비동기 코드 작성이 더 간단 해집니다.


0

이 패턴을 처리하는 방법은 모든 I / O가 비동기인지 확인하는 것입니다. 동기 I / O 메소드는 I / O 대상 (네트워크, 파일 시스템 등)의 응답을 기다리는 동안 현재 스레드를 차단합니다.

고려해야 할 또 다른 사항은 await반환 값이 필요하거나 다른 작업을 수행하기 전에 대기중인 코드를 완료해야 할 때 사용해야한다는 것입니다. 이 중 하나가 필요하지 않은 경우를 사용하여 비동기 메소드를 "실행 및 잊어 버릴 수 있습니다" Task.Run.

경우에 따라서, 컴퓨팅 자원을 가장 효율적으로 사용하기 위해, RemoveRoles모든 I / O를 수행, 그것은이되어야 await RemoveRolesAsync하고 호출하는 I / O 방법은 RemoveRolesAsync또한 비동기 (그리고 아마도 기다려온)이어야한다.

성능이 가장 중요하지 않은 경우 비동기 스레드에서 일부 동기 I / O를 수행하는 것이 좋습니다. 그래도 기술 부채입니다. (이 경우 코드가 실행되는 위치에 따라을 사용하여 첫 번째 비동기 메소드를 호출 할 수 있습니다ConfigureAwait .)

다음은 모범 사례에 대한 심층적 인 내용입니다. https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

여기 ASP.NET, WebAPI 등 같은 다른 환경에서 ConfigureAwait의 행동에 대한 몇 가지주의 사항이있다 - /programming/13489065/best-practice-to-call-configureawait-for-all-server-side -암호


2
Task.Run으로 코드를 실행하거나 잊어 버리면 안됩니다. 모든 작업을 기다려야합니다. 작업을 기다리지 않고 예외가 "관찰되지 않은"상태에서 작업을 가비지 수집하면 런타임에서 UnobservedTaskException이 발생하여 프레임 워크 버전에 따라 응용 프로그램이 중단 될 수 있습니다.
Triynko
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.