4

タスクを非同期的に遅延させるのに問題があります。私は、数十/数十万の非同期実行スクリプトの規模で実行する必要があるアプリケーションを作成しています。私は C# アクションを使用してこれを行っていますが、特定のシーケンスの実行中に、スクリプトを適切に実行するために、外部リソースが期待される状態になるまで待機する必要がある場合があります。最初は Thread.Sleep() を使用してこれを書きましたが、それがアプリケーションのパフォーマンスの魚雷であることが判明したため、非同期スリープの async/await を調べています。しかし、実際に一時停止を待つことはできません! 誰かがこれを説明できますか?

static void Main(string[] args)
    {
        var sync = new List<Action>();
        var async = new List<Action>();

        var syncStopWatch = new Stopwatch();
        sync.Add(syncStopWatch.Start);
        sync.Add(() => Thread.Sleep(1000));
        sync.Add(syncStopWatch.Stop);
        sync.Add(() => Console.Write("Sync:\t" + syncStopWatch.ElapsedMilliseconds + "\n"));

        var asyncStopWatch = new Stopwatch();
        sync.Add(asyncStopWatch.Start);
        sync.Add(async () => await Task.Delay(1000));
        sync.Add(asyncStopWatch.Stop);
        sync.Add(() => Console.Write("Async:\t" + asyncStopWatch.ElapsedMilliseconds + "\n"));

        foreach (Action a in sync)
        {
            a.Invoke();
        }

        foreach (Action a in async)
        {
            a.Invoke();
        }
    }

実行結果は次のとおりです。

シンクロ:999

非同期: 2

非同期に待機させるにはどうすればよいですか?

4

1 に答える 1

7

で問題が発生していasync voidます。asyncラムダを に渡すActionと、コンパイラはasync voidメソッドを作成しています。

ベスト プラクティスとして、 を避ける必要がありますasync void

これを行う 1 つの方法は、実際にアクションのリストをList<Func<Task>>ではなく にすることですList<Action>async Taskこれにより、メソッドの代わりにメソッドをキューに入れることができますasync void

これは、「実行」コードがTask完了するたびに待機する必要があることを意味します。また、同期メソッドは、シグネチャTask.FromResult(0)と一致するように、返す必要があるか、そのようなものにする必要があります。Func<Task>

より広い範囲のソリューションが必要な場合は、独自のキューを作成するのではなく、TPL Dataflow を強く検討することをお勧めします。

于 2013-07-09T18:44:21.100 に答える