programing

인터페이스에서 작업을 반환해야 하는 경우 무작동 구현을 수행하는 가장 좋은 방법은 무엇입니까?

lovejava 2023. 5. 14. 09:57

인터페이스에서 작업을 반환해야 하는 경우 무작동 구현을 수행하는 가장 좋은 방법은 무엇입니까?

아래 코드에서 인터페이스로 인해 클래스는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();
        }
    }
}

오늘은 작업을 사용하는 것을 추천합니다.이 작업을 수행하기 위한 작업을 완료했습니다.


.net 4.6 이전 버전:

사용.Task.FromResult(0)또는Task.FromResult<object>(null)생성하는 것보다 오버헤드가 더 적게 발생합니다.Task무표정하게를 생성할 때Task결과가 미리 결정된 경우에는 스케줄링 오버헤드가 발생하지 않습니다.

사용에 대한 Reed Copsey의 답변에 추가하기Task.FromResult완료된 작업의 모든 인스턴스가 동일하기 때문에 이미 완료된 작업을 캐시하면 성능을 더욱 향상시킬 수 있습니다.

public static class TaskExtensions
{
    public static readonly Task CompletedTask = Task.FromResult(false);
}

와 함께TaskExtensions.CompletedTask전체 앱 도메인에서 동일한 인스턴스를 사용할 수 있습니다.


의 최신 버전.Net Framework(v4.6)는 정적 속성을 사용하여 이를 추가합니다.

Task completedTask = Task.CompletedTask;

Task.Delay(0)승인된 답변은 완료된 복사본의 캐시된 복사본이므로 좋은 접근 방식이었습니다.Task.

4.6 기준으로 현재Task.CompletedTask그것의 목적에서 더 명확하지만, 뿐만 아니라.Task.Delay(0)여전히 단일 캐시 인스턴스를 반환합니다. 동일한 단일 캐시 인스턴스를 반환합니다.Task.CompletedTask.

어느 것도 캐시된 특성이 일정하게 유지되지는 않지만, 최적화만큼만 구현에 의존하는 구현 의존적 최적화로서(즉, 구현이 여전히 유효한 것으로 변경된 경우에도 올바르게 작동할 것입니다),Task.Delay(0)승인된 답변보다 더 좋았습니다.

return Task.CompletedTask; // this will make the compiler happy

최근에 이 문제가 발생하여 메서드가 유효하지 않다는 경고/오류가 계속 발생했습니다.

우리는 컴파일러를 배치하는 사업을 하고 있으며 이것은 그것을 정리합니다.

    public async Task MyVoidAsyncMethod()
    {
        await Task.CompletedTask;
    }

이것은 지금까지 나온 모든 조언들 중에서 가장 좋은 것들을 모아줍니다.메소드에서 실제로 무언가를 수행하는 경우가 아니면 반환 명세서가 필요하지 않습니다.

지정된 유형을 반환해야 하는 경우:

Task.FromResult<MyClass>(null);

나는 그것을 선호합니다.Task completedTask = Task.CompletedTask; 4 방식은 메서드를 void를 입니다.Net 4.6, 그러나 다른 접근 방식은 방법을 비동기로 표시하고 void를 반환하는 것입니다.

    public async Task WillBeLongRunningAsyncInTheMajorityOfImplementations()
    {
    }

경고(CS1998 - 대기 식이 없는 비동기 함수)가 표시되지만 이 경우 무시해도 무방합니다.

만약 당신이 제네릭을 사용한다면, 모든 대답은 우리에게 컴파일 오류를 줄 것입니다.사용할 수 있습니다.return default(T);자세한 설명을 위해 아래 샘플을 참조하십시오.

public async Task<T> GetItemAsync<T>(string id)
            {
                try
                {
                    var response = await this._container.ReadItemAsync<T>(id, new PartitionKey(id));
                    return response.Resource;
                }
                catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
                {

                    return default(T);
                }

            }
return await Task.FromResult(new MyClass());

언급URL : https://stackoverflow.com/questions/13127177/if-my-interface-must-return-task-what-is-the-best-way-to-have-a-no-operation-imp