1. ホーム
  2. c#

[解決済み] 私のインターフェースがTaskを返さなければならない場合、操作不要の実装を持つための最良の方法は何ですか?

2022-03-18 14:46:59

質問

以下のコードでは、インターフェイスの関係で、クラス LazyBar はそのメソッドからタスクを返さなければなりません (そして議論のために変更することはできません)。もし LazyBar このメソッドから No-Operation タスクを返す最良の方法は何でしょうか?

で行っています。 Task.Delay(0) を呼び出した場合、パフォーマンス上の副作用があるかどうかを知りたいです。 ロット (議論のために、1秒間に数百回とします)。

  • この構文糖は、何か大きなものに巻き戻されるのでしょうか?
  • アプリケーションのスレッドプールを詰まらせることになりませんか?
  • コンパイラは 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();
        }
    }
}

解決方法は?

今日、私がお勧めするのは タスク.CompletedTask を使えば、これを実現することができます。


.net 4.6以前。

使用方法 Task.FromResult(0) または Task.FromResult<object>(null) を作成するよりもオーバーヘッドが少なくなります。 Task をno-op式で指定します。 を作成する場合 Task のように、結果があらかじめ決まっている場合は、スケジューリングのオーバーヘッドが発生しません。