Microsoft MVP성태의 닷넷 이야기
ValueTask를 multiple await 하지 말라는데 [링크 복사], [링크+제목 복사],
조회: 597
글쓴 사람
eric (gss9282 at gmail.com)
홈페이지
첨부 파일
 
(연관된 글이 2개 있습니다.)

https://devblogs.microsoft.com/dotnet/understanding-the-whys-whats-and-whens-of-valuetask/

이 게시글이나 msdn 보면 ValueTask에 대해서 multiple await가 안좋다 하는데


제가 다음과 같이

var t = GetValue();
await t;
await t;

private async ValueTask<int> GetValue()
{
    if (cachedValue is null)
    {
        await Task.Delay(500);
        cachedValue = 5;
    }
    return cachedValue.Value;
}

이러면 CA2012 경고가 나오긴 하는데
작동은 잘됩니다.

어떠한 케이스에서 multiple await를 쓰면 예외가 터지는건가요?


[연관 글]






[최초 등록일: ]
[최종 수정일: 6/10/2025]


비밀번호

댓글 작성자
 



2025-06-11 04시00분
해당 글을 잠시 읽어보니까, 그 글에 답이 잘 나오는군요. ^^

multiple await을 할 때 예외가 발생할 수 있는 경우는 ValueTask가 IValueTaskSource를 구현한 개체를 감싸서 반환한 경우입니다. 예제로 든 경우는 TResult를 반환한 값이기 때문에 경고는 나와도 문제는 없습니다.

참고로, IValueTaskSource를 구현한 개체를 반환하더라도 문제가 안 되는 경우도 있습니다. 문제가 되는 경우는, 해당 문서에서도 예를 들어 나오지만 Pool에 관리가 된 경우입니다. 가령 예제에서 GetValue가 풀링된 개체를 담은 ValueTask를 반환했다고 가정하면 두 번째 await 호출 시에 이미 해당 개체는 풀에 반환돼 다른 값을 가지고 있거나 반환되면서 값이 초기화돼 정상적인 값을 구할 수 없게 될 것입니다.

게다가, IValueTaskSource를 감싼 경우라면 await을 분리해서 호출하는 경우에도 문제가 발생할 수 있습니다. 즉, 다음과 같이 직접 호출하는 식으로 바꿔야 합니다.

var t = await GetValue(); // 이렇게 메서드 호출에 직접 await 사용

왜냐하면, IValueTaskSource가 반환하면서 직접적인 값을 ValueTask<TResult>의 TResult를 '값 복사'해서 반환해 사용해야 안전한 것입니다. 그렇지 않고 ValueTask<TResult>로 받고 이후에 await을 하게 되면 위에서 설명했던 것과 마찬가지로 풀링에 이미 반환돼 다른 목적으로 사용될 수 있으므로 오동작을 할 수 있는 것입니다.

-----------------

아래의 글에 정리했으니 참고하세요.

C# - IValueTaskSource로 인해 주의가 필요한 ValueTask 호출
; https://www.sysnet.pe.kr/2/0/13952
정성태

... 61  62  63  64  65  66  67  [68]  69  70  71  72  73  74  75  ...
NoWriterDateCnt.TitleFile(s)
891임동찬7/6/201018157        답변글 [추가]: [답변]: 아래 887번에 대한 추가 질문
892정성태7/6/201015301            답변글 [답변]: [추가]: [답변]: 아래 887번에 대한 추가 질문
888김재영7/5/201015098TFS에 반드시! SQL Report랑 SharePoint(or WSS)가 붙어야 합니까? [2]
887임동찬7/2/201016391WCF sendTimeout에 관하여... [1]
886김재영6/16/201016407스레드 선언시 (Parameterized/)ThreadStart에 정의되는 메소드의 위치에 질문이 있습니다. [3]
885장근배6/13/201023886Win32Exception 창 핸들 에러 [1]
883채동민6/10/201016111비동기 DB 쿼리관련 질문
884정성태6/10/201017479    답변글 [답변]: 비동기 DB 쿼리관련 질문
881최준영5/24/201017314load되지않은 아이템 load하는 방법? [1]
880임상일5/10/201019508VS2010 TestManager를 통한 UI Test 관련 질문입니다. [2]파일 다운로드1
879정용훈5/3/201020743wcf 인증 문제 [2]
878채동민4/20/201019899WCF에서 maxItemsInObjectGraph 오류 관련 질문드립니다. [2]
872날쌘돌이4/8/201022469Windows7 에서 IIS에서 폼인증 으로 디버깅.. [1]파일 다운로드1
871영초4/7/201017815실버라이트로 스캐너 구동 프로그램이 가능할까요? [1]
869김재영4/6/201016779이미 실행된 어셈블리 컨트롤 권한을 다른 어셈블리에서 가져올 수 있습니까? [2]
868Lime3/5/201020375WCF 에서의 DataTable 사용 [2]
867Dani...2/18/201020638Question - HTTP 401.3 on DELETE, PUT verbs [6]파일 다운로드1
865박근대2/16/201017091WCF 오류 문의. [1]
863날쌘돌이1/31/201019405ActiveX Cab에서 닷넷 dll 등록 [1]
862장근배1/28/201017236AppPolId를 알 수 있는 방법이 있는지요? [1]
864장근배2/1/201016899    답변글 [답변]: AppPolId를 알 수 있는 방법이 있는지요?
858생초보1/26/201017195안녕하세요.. 파일 생성 처리 문제로 .... [2]
857꼭지1/22/201023116How to support Basic + Windows authentication mode in WCF(RESTful service) [4]파일 다운로드2
856질의자1/13/201020905vcredist_x86 배포 관련 여쭙습니다. [1]
855임동찬1/13/201019209이벤트 핸들러와 쓰레드의 관계 2 [4]파일 다운로드2
854임동찬1/12/201019393이벤트 핸들러와 쓰레드의 관계 [1]
... 61  62  63  64  65  66  67  [68]  69  70  71  72  73  74  75  ...