아래 코드에서 인터페이스로 인해 클래스 LazyBar
는 메서드에서 작업을 반환해야합니다 (인수를 변경할 수 없음). LazyBar
신속하고 동 기적으로 실행된다는 점에서 구현이 특이한 경우 -메소드에서 비 작동 태스크를 리턴하는 가장 좋은 방법은 무엇입니까?
Task.Delay(0)
아래에 갔지만 함수가 많이 호출되면 성능에 부작용이 있는지 알고 싶습니다 (인수를 위해 초당 수백 번 말하십시오).
- 이 구문 설탕은 큰 것으로 풀리나요?
- 내 응용 프로그램의 스레드 풀이 막히기 시작합니까?
- 컴파일러 식칼은
Delay(0)
다르게 처리하기에 충분 합니까? - 다를까요
return Task.Run(() => { });
?
더 좋은 방법이 있습니까?
using System.Threading.Tasks;
namespace MyAsyncTest
{
internal interface IFooFace
{
Task WillBeLongRunningAsyncInTheMajorityOfImplementations();
}
/// <summary>
/// An implementation, that unlike most cases, will not have a long-running
/// operation in 'WillBeLongRunningAsyncInTheMajorityOfImplementations'
/// </summary>
internal class LazyBar : IFooFace
{
#region IFooFace Members
public Task WillBeLongRunningAsyncInTheMajorityOfImplementations()
{
// First, do something really quick
var x = 1;
// Can't return 'null' here! Does 'Task.Delay(0)' have any performance considerations?
// Is it a real no-op, or if I call this a lot, will it adversely affect the
// underlying thread-pool? Better way?
return Task.Delay(0);
// Any different?
// return Task.Run(() => { });
// If my task returned something, I would do:
// return Task.FromResult<int>(12345);
}
#endregion
}
internal class Program
{
private static void Main(string[] args)
{
Test();
}
private static async void Test()
{
IFooFace foo = FactoryCreate();
await foo.WillBeLongRunningAsyncInTheMajorityOfImplementations();
return;
}
private static IFooFace FactoryCreate()
{
return new LazyBar();
}
}
}
답변
no-op 표현식으로 작성하는 것보다 Task.FromResult(0)
또는 사용하면 Task.FromResult<object>(null)
오버 헤드가 줄어 듭니다 Task
. Task
미리 결정된 결과로을 만들 때 예약 오버 헤드가 없습니다.
오늘은 Task.CompletedTask 를 사용 하여이 작업 을 수행하는 것이 좋습니다 .
답변
를 사용하는 것에 대한 Reed Copsey의 답변 에 추가하기 Task.FromResult
위해 완료된 작업의 모든 인스턴스가 동일하기 때문에 이미 완료된 작업을 캐시하면 성능을 훨씬 향상시킬 수 있습니다.
public static class TaskExtensions
{
public static readonly Task CompletedTask = Task.FromResult(false);
}
함께 TaskExtensions.CompletedTask
사용하면 전체 응용 프로그램 도메인 전체에 동일한 인스턴스를 사용할 수 있습니다.
닷넷 프레임 워크 (V4.6)의 최신 버전은 추가 단지 그와 Task.CompletedTask
정적 속성
Task completedTask = Task.CompletedTask;
답변
Task.Delay(0)
허용 된 답변에서와 같이 그것이 완성 된 캐시 된 사본이므로 좋은 접근 방식이었습니다 Task
.
4.6 현재 Task.CompletedTask
목적에 따라 더 분명한 것이 있지만 Task.Delay(0)
여전히 단일 캐시 인스턴스를 반환 할 뿐만 아니라 동일한 단일 캐시 인스턴스를 반환합니다Task.CompletedTask
.
의 사용도의 캐시 특성은 일정하게 유지 보장,하지만 구현에 의존 최적화 등이다 구현에 의존 최적화로 (구현은 여전히 유효 뭔가 변경 한 경우 즉, 그들은 여전히 제대로 작동 것) Task.Delay(0)
이었다을 허용 된 답변보다 낫습니다.
답변
최근 에이 문제가 발생하여 메소드가 무효라는 경고 / 오류가 계속 발생했습니다.
우리는 컴파일러를 배치하는 사업을하고 있으며 이것을 정리합니다.
public async Task MyVoidAsyncMethod()
{
await Task.CompletedTask;
}
이것은 지금까지 모든 조언 중 최고의 것을 모은 것입니다. 실제로 메소드에서 무언가를 수행하지 않는 한 return 문은 필요하지 않습니다.
답변
return Task.CompletedTask; // this will make the compiler happy
답변
지정된 유형을 반환해야 할 경우 :
Task.FromResult<MyClass>(null);
답변
Task completedTask = Task.CompletedTask;
.Net 4.6 의 솔루션을 선호 하지만 다른 방법은 메소드를 비동기로 표시하고 void를 반환하는 것입니다.
public async Task WillBeLongRunningAsyncInTheMajorityOfImplementations()
{
}
경고가 표시되지만 (CS1998-대기 표현식이없는 비동기 함수)이 컨텍스트에서는 무시해도 안전합니다.