3

一度に 3 つのアイテムを処理する必要がある関数があり、合計所要時間が x 秒未満の場合、スレッドは残りの秒数スリープしてから先に進む必要があります。

だから私は次のことをやっています:

    private void ProcessItems()
    {
        for (int i = 0, n = items.Count; i < n; i++)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            batch.Add(items[i]);

            if (batch.Count == 3 || i >= items.Count - 3)
            {
                List<Task> tasks = new List<Task>(3);

                foreach (Item item in batch)
                    tasks.Add(Task.Factory.StartNew(() => ProcessItem(item)));

                Task.WaitAll(tasks.ToArray());

                batch.Clear();
            }

            stopwatch.Stop();

            int elapsed = (int)stopwatch.ElapsedMilliseconds;
            int delay = (3000) - elapsed;

            if (delay > 0)
                Thread.Sleep(delay);
        }
    }

ProcessItem 関数は、webrequest を作成し、応答 (コールバック) を処理します。時間のかかる機能です。

ただし、タスクを正しく理解していれば、スレッドは複数のタスクを持つことができます。したがって、スレッドをスリープ状態にすると、他のタスクが影響を受ける可能性があります。

上記を達成するためのより効率的な方法はありますか? Parallel.Foreach 内でタスクを使用できますか?

4

3 に答える 3

2

Tasks run on automatically managed threads. There is nothing intrinsically wrong with blocking a thread. It is just a little wasteful.

Here is how I would implement this very cleanly:

MyItem[] items = ...;
foreach(MyItem[] itemsChunk in items.AsChunked(3)) {
 Parallel.ForEach(itemsChunk, item => Process(item));
 //here you can insert a delay
}

This wastes not a single thread and is trivially simple. Parallel.ForEach used the current thread to process work items as well, so it does not sit idle. You can add your delay logic as well. Implementing AsChunked is left as an exercise for the reader... This function is supposed to split a list into chunks of the given size (3). The good thing about such a helper function is that it untangles the batching logic from the important parts.

于 2013-10-13T13:17:19.320 に答える
1

使用する

Task.Delay 

代わりは

    static async Task DoSomeProcess()
    {
        await Task.Delay(3000);
    }

そうです、Thread.Sleep は他のタスクをブロックします

はい、async/await パターンを Parallel と組み合わせることができます。

于 2013-10-13T13:14:06.923 に答える