Task <int>는 어떻게 int가 되나요?


116

이 방법이 있습니다.

async Task<int> AccessTheWebAsync()
{ 
    HttpClient client = new HttpClient();

   Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

   // You can do work here that doesn't rely on the string from GetStringAsync.
   DoIndependentWork();

   string urlContents = await getStringTask;
   //The thing is that this returns an int to a method that has a return type of Task<int>
   return urlContents.Length;
}

Task<int>와 사이에 암시 적 변환이 발생 int합니까? 그렇지 않다면 무슨 일이 일어나고 있습니까? 작동하려면 어떻게 구현됩니까?


1
계속 읽으십시오 . 컴파일러가 async키워드 를 기반으로 처리한다고 가정합니다 .
D Stanley

1
@Freeman,이 위대한 설명을 봐 : stackoverflow.com/a/4047607/280758
qehgt

답변:


171

Task <>와 int간에 암시 적 변환이 발생합니까?

아니. 이 방법의 한 부분입니다 async/ await작품.

asynchas 선언 된 모든 메서드는 다음과 같은 반환 유형을 가져야합니다.

  • void (가능하면 피하십시오)
  • Task (완료 / 실패 통지 이외의 결과 없음)
  • Task<T>( T비동기 방식 의 논리적 결과 유형 )

컴파일러는 모든 적절한 래핑을 수행합니다. 요점은 비동기 적으로 반환 한다는 것입니다 . 실제 메서드가 아직 완료되지 않은 첫 번째 표현식에 도달 하면 반환되므로 메서드가 반환 urlContents.Length되도록 만들 수 없습니다 . 따라서 대신 비동기 메서드 자체가 완료되면 완료되는를 반환합니다 .intawaitTask<int>

참고 await반대하지는 - 그것은 펼쳤다Task<T>A와 T이 라인이 어떻게 작동 값 :

string urlContents = await getStringTask;

... 물론 비동기식으로 래핑을 해제하지만 Result작업이 완료 될 때 까지을 사용 하면 차단됩니다. ( awaitawaitable 패턴을 구현하는 다른 유형을 풀 수 있지만 Task<T>가장 자주 사용할 가능성이있는 유형입니다 .)

이 이중 래핑 / 언 래핑은 비동기를 구성 할 수있게합니다. 예를 들어, 사용자를 호출하고 결과를 두 배로 늘리는 다른 비동기 메서드를 작성할 수 있습니다.

public async Task<int> AccessTheWebAndDoubleAsync()
{
    var task = AccessTheWebAsync();
    int result = await task;
    return result * 2;
}

(또는 단순히 return await AccessTheWebAsync() * 2;물론입니다.)


3
그것이 어떻게 작동하는지에 대한 세부 사항을 제공 할 수 있습니까?
Freeman

8
+1 항상 그렇듯이 좋은 답변입니다. 그리고 왜 그렇게 빨리 쓰는거야?!
Felix K.

9
+1 : 방금 async/를 조사하기 시작했는데 await이게 매우 직관적이지 않습니다. IMO, 상기 키워드 또는 유사한이 있어야 return이 명확 예를 만들기 위해 return async result;(같은 방식으로 그 await result"펼쳤다"는 T에서 Tast<T>).
dav_i

2
@JonSkeet 그러나 그것은 await- T foo = someTaskT;당신이 "암묵적으로 유형 Task<T>을 변환 할 수 없습니다"를 얻을 것입니다 T-내가 역에 대한 키워드를 갖는 것이 더 합리적이라고 주장하는 것과 같은 방식으로 의미가 없습니다 Task<T>. 나는 보풀을 제거하는 것이 전부이지만이 경우 async메서드 내에서 불필요한 난독 화를 제공한다고 생각합니다 . (권력자가 이미 / 음성 코딩 때문에 분명히 요점은 이론에 불과!)
dav_i

2
@dav_i : 할당 은 의미가 없지만 나머지는 이해가됩니다. 그리고 유용하지 않을 수도 있지만 전체 진술이 의미가있는 경우가 있습니다. 메서드가 이미 선언되어 있으므로 async충분하다고 생각합니다.
Jon Skeet 2013

18

Task를 int로 변환 할 필요가 없습니다. 작업 결과를 사용하기 만하면됩니다.

int taskResult = AccessTheWebAndDouble().Result;

public async Task<int> AccessTheWebAndDouble()
{
    int task = AccessTheWeb();
    return task;
}

가능한 경우 값을 반환하고 그렇지 않으면 0을 반환합니다.


20
그것은 내가 요청한 것이 아닙니다.
프리먼

16
이것은 질문에 대한 답이 아닙니다. 그러나 더 중요한 것은 이것은 매우 나쁜 조언 입니다. 거의 사용 하지 말아야 합니다 Result. 교착 상태가 발생할 수 있습니다! 예를 들어 다음 워크 플로를 고려하십시오. (1) "잔디를 깎습니다"라는 메모를 작성합니다. (2) 잔디를 깎을 때까지 기다립니다 . (3) 샌드위치 먹기, (4) 메모에 적힌대로하십시오. "이 워크 플로에서는 2 단계가 동기 대기 이므로 샌드위치를 ​​먹거나 잔디를 깎지 않습니다. 뭔가 당신이 할 것입니다 미래에 당신이 여기에 설명되어 그러나 워크 플로입니다..
에릭 Lippert의

@EricLippert : 당신의 예를 명확하지 않습니다. Result가 대기하지 않을 때 어떻게 교착 상태를 유발하는지 설명해 주시겠습니까?
CharithJ 2019

3
Await는 결과를 기다리는 동안 무언가를하는 것을 의미하며 결과를 계산하기위한 작업을 포함 할 수 있습니다. 그러나 동기식 대기는 대기하는 동안 아무 작업도 수행하지 않으므로 작업이 완료되는 것을 막을 수 있습니다.
Eric Lippert

1
@EricLippert. 동일한 문제가 있습니까? 'Task.Run (() => AccessTheWebAndDouble ()). Result;'
CharithJ 2019
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.