거기 있니?어떤시나리오 작성 방법은 다음과 같습니다.
public async Task<SomeResult> DoSomethingAsync()
{
// Some synchronous code might or might not be here... //
return await DoAnotherThingAsync();
}
대신이 :
public Task<SomeResult> DoSomethingAsync()
{
// Some synchronous code might or might not be here... //
return DoAnotherThingAsync();
}
말이 되겠습니까?
왜 사용 하는가?return await
직접 돌아올 수있을 때 구성Task<T>
안쪽에서DoAnotherThingAsync()
기도?
나는 코드를 본다.return await
여러 곳에서 나는 뭔가를 놓쳐 야한다고 생각합니다. 그러나 내가 이해하는 한,이 경우에는 async / 키워드를 기다리지 않고 Task를 직접 반환하는 것이 기능적으로 동일합니다. 추가 오버 헤드를 추가하는 이유await
층?
다음 경우에 한 가지 비열한 경우가 있습니다.return
정상적인 방법으로return await
...에서async
메소드가 다르게 동작합니다.using
(또는 더 일반적으로return await
안에try
블록).
다음 두 가지 버전의 메소드를 고려하십시오.
Task<SomeResult> DoSomethingAsync()
{
using (var foo = new Foo())
{
return foo.DoAnotherThingAsync();
}
}
async Task<SomeResult> DoSomethingAsync()
{
using (var foo = new Foo())
{
return await foo.DoAnotherThingAsync();
}
}
첫 번째 방법은Dispose()
그만큼Foo
되 자마자DoAnotherThingAsync()
메서드가 반환됩니다. 실제로 완료되기 훨씬 전에 발생합니다. 즉, 첫 번째 버전은 버그가있을 수 있습니다 (왜냐하면Foo
너무 빨리 처리됩니다.), 두 번째 버전은 정상적으로 작동합니다.
foo.DoAnotherThingAsync().ContinueWith(_ => foo.Dispose());
- ghordDispose()
보고void
. 너는 비슷한 것을 필요로 할거야.return foo.DoAnotherThingAsync().ContinueWith(t -> { foo.Dispose(); return t.Result; });
. 하지만 두 번째 옵션을 사용할 수있는 이유는 무엇입니까? - svick{ var task = DoAnotherThingAsync(); task.ContinueWith(_ => foo.Dispose()); return task; }
. 유스 케이스는 매우 간단합니다. .NET 4.0 (대부분)과 같은 경우, 비동기 코드를이 방식으로 작성할 수 있습니다.이 방식으로 4.5 앱에서 제대로 호출됩니다. - ghordFoo
반환 된 후에 만Task
완료하지 않습니다. 동시성을 불필요하게 도입하기 때문에 마음에 들지 않습니다. - svick
필요없는 경우async
(즉,Task
직접) 사용하지 마십시오.async
.
몇 가지 상황이 있습니다.return await
당신이 가진 것처럼 유용하다.두비동기 작업 :
var intermediate = await FirstAsync();
return await SecondAwait(intermediate);
자세한 내용async
성능은 Stephen Toub 's를 참조하십시오.MSDN 기사과비디오주제에.
최신 정보:나는블로그 게시물그것은 훨씬 더 자세하게 설명됩니다.
await
두 번째 경우에 유용합니까? 왜 안돼?return SecondAwait(intermediate);
? - Matt Smithreturn SecondAwait(intermediate);
이 경우에도 목표를 달성 할 수 있을까요? 나는 생각한다.return await
여기에도 중복됩니다 ... - TX_await
첫 번째 줄에서는 두 번째 줄에서도 사용해야합니다. - svickasync
버전에서 사용할적게동기화 버전보다 리소스 (스레드)가 많습니다. - svickSecondAwait
CS4016 : 이것은 비동기식 메소드이므로, 리턴 표현식은 & # 39; 문자열 & # 39; 유형이어야합니다. & lt; 작업 & lt; 문자열 & gt; & quot; & quot; - svick
네가하고 싶은 유일한 이유는 다른 것이 있으면await
이전 코드에서, 또는 결과를 조작하기 전에 결과를 조작하는 경우. 그것이 일어날 수있는 또 다른 방법은try/catch
예외가 처리되는 방식이 변경됩니다. 네가 맞다면 그 중 하나를 수행하지 않는다면 메소드를 만드는 오버 헤드를 추가 할 이유가 없다.async
.
return await
자식 호출의 태스크를 반환하는 대신에) 필요하다.이전 코드에서 기다리고있는 다른 것이 있더라도. 설명해 주시겠습니까? - TX_async
그러면 첫 번째 과제는 어떻게 기다리고 있을까요? 메소드를 다음과 같이 표시해야합니다.async
당신이 사용하고 싶다면어떤기다리고있어. 메소드가 다음과 같이 표시되면async
너는await
이전 코드에서는await
두 번째 비동기 작업은 적절한 유형이어야합니다. 방금 제거한 경우await
반환 값이 적절한 유형이 아니므로 컴파일되지 않습니다. 이 방법은async
결과는 항상 태스크에 랩핑됩니다. - Servyasync
메서드를 사용하여 작업을 반환하지 않으면 작업의 결과를 반환 한 다음 래핑됩니다. - ServyTask<Type>
명시 적으로, whileasync
돌아 오는 것을 명령하다Type
(컴파일러 자체가Task<Type>
). - noseratioasync
연속체를 명시 적으로 연결하기위한 문법적 설탕 일뿐입니다. 너는 몰라.필요한 것
async
무엇이든 할 수 있지만, 비범 한 비동기 작업을 수행 할 때는극적으로함께 일하기가 쉽다. 예를 들어, 제공 한 코드가 실제로 원하는대로 오류를 전달하지 못하고 더 복잡한 상황에서 올바르게 수행하면 훨씬 더 어려워집니다. 너는 절대로필요한 것
async
, 내가 기술 한 상황은 그것을 사용하는 가치를 부가하는 곳이다. - Servy
결과를 기다리는 또 다른 경우는 다음과 같습니다.
async Task<IFoo> GetIFooAsync()
{
return await GetFooAsync();
}
async Task<Foo> GetFooAsync()
{
var foo = await CreateFooAsync();
await foo.InitializeAsync();
return foo;
}
이 경우,GetIFooAsync()
~의 결과를 기다려야한다.GetFooAsync
유형이T
두 가지 방법이 다르다.Task<Foo>
에 직접 할당 할 수 없다.Task<IFoo>
. 하지만 결과를 기다리고 있다면Foo
어느~이다.에 직접 할당 할 수있는IFoo
. 그런 다음 비동기 메서드는 내부에서 결과를 리 패키징합니다.Task<IFoo>
그리고 멀리 가라.
달리 간단한 "썽크"메서드를 비동기로 만들면 메모리에 비동기 상태 시스템이 만들어지며 비동기식 모드 시스템에서는 그렇지 않습니다. 더 비효율적 인 버전을 사용하는 것은 종종 비효율적 인 버전을 사용하는 것을 가리킬 수 있지만 (사실입니다), 이는 정지 상태 인 경우 해당 메소드가 "리턴 / 연속 스택"과 관련되어 있다는 증거가 없음을 의미합니다. 때로는 걸림쇠를 이해하는 것을 더 어렵게 만듭니다.
그래서 예, 퍼프가 중요하지 않을 때 (그리고 대개는 그렇지 않습니다) 나는이 모든 썽크 메서드에 비동기를 던져서 나중에 비상 정지 상태를 진단 할 수있게 도와줍니다. 썽크 (thunk) 방법은 시간이 지남에 따라 진화 해 나간다. 던진 것이 아니라 잘못 된 작업을 반드시 되돌려 놓을 것이다.
이것은 또한 나 혼란스럽고 이전 답변이 실제 질문을 간과했다고 생각합니다.
내부 DoAnotherThingAsync () 호출에서 Task를 직접 반환 할 수있는 경우 return을 사용하는 이유는 무엇입니까?
가끔 당신 이요.사실은~을 원한다Task<SomeType>
, 그러나 대부분의 경우 실제로 인스턴스를 원한다.SomeType
, 즉 작업의 결과입니다.
귀하의 코드에서 :
async Task<SomeResult> DoSomethingAsync()
{
using (var foo = new Foo())
{
return await foo.DoAnotherThingAsync();
}
}
구문에 익숙하지 않은 사람 (예를 들어)은이 메서드가Task<SomeResult>
, 표시되어 있기 때문에async
, 실제 리턴 유형은 다음과 같습니다.SomeResult
.
방금 사용하면return foo.DoAnotherThingAsync()
, 컴파일하지 않는 Task를 반환 할 것입니다. 올바른 방법은 작업 결과를 반환하는 것입니다.return await
.
var task = DoSomethingAsync();
너에게 과제를 주겠다.T
- Shoeasync/await
의회. 나의 이해에,Task task = DoSomethingAsync()
, 동안Something something = await DoSomethingAsync()
둘 다 작동합니다. 첫 번째는 적절한 작업을 제공하고 두 번째는await
키워드를 사용하면결과완료 후 작업에서. 예를 들어 나는Task task = DoSomethingAsync(); Something something = await task;
. - heltonbiker