Time delay in For loop in c#

2019-01-24 05:37发布

how can i use a time delay in a loop after certain rotation? Suppose:

for(int i = 0 ; i<64;i++)
{
........
}

i want 1 sec delay after each 8 rotation.

标签: c# timer
6条回答
做自己的国王
2楼-- · 2019-01-24 06:11

Here is the implementation I came up with. It's generic, so you can easily reuse it for your use case. (it aligns with what @Servy suggested)

public static async Task ForEachWithDelay<T>(this ICollection<T> items, Func<T, Task> action, double interval)
{
    using (var timer = new System.Timers.Timer(interval))
    {
        var task = new Task(() => { });
        int remaining = items.Count;
        var queue = new ConcurrentQueue<T>(items);

        timer.Elapsed += async (sender, args) =>
        {
            T item;
            if (queue.TryDequeue(out item))
            {
                try
                {
                    await action(item);
                }
                finally
                {
                    // Complete task.
                    remaining -= 1;

                    if (remaining == 0)
                    {
                        // No more items to process. Complete task.
                        task.Start();
                    }
                }
            }
        };

        timer.Start();

        await task;
    }
}

And then use it as so:

var numbers = Enumerable.Range(1, 10).ToList();
var interval = 1000; // 1000 ms delay
numbers.ForEachWithDelay(i => Task.Run(() => Console.WriteLine(i + " @ " + DateTime.Now)), interval);

which prints this:

1 @ 2/2/2016 9:45:37 AM
2 @ 2/2/2016 9:45:38 AM
3 @ 2/2/2016 9:45:39 AM
4 @ 2/2/2016 9:45:40 AM
5 @ 2/2/2016 9:45:41 AM
6 @ 2/2/2016 9:45:42 AM
7 @ 2/2/2016 9:45:43 AM
8 @ 2/2/2016 9:45:44 AM
9 @ 2/2/2016 9:45:45 AM
10 @ 2/2/2016 9:45:46 AM
查看更多
老娘就宠你
3楼-- · 2019-01-24 06:12

Try this simpler version without dependency on async or await or TPL.

  1. Spawns 50 method calls ,
  2. sleeps for 20 secs,
  3. checks it 20 or x items are complete.
  4. if not sleeps again for 20 secs
  5. if yes resumes loop

Code here

 foreach (var item in collection)
            {
                if (cnt < 50)
                {
                    cnt++;
                    DoWork(item);
                }
                else
                {
                    bool stayinLoop = true;
                    while (stayinLoop)
                    {
                        Thread.Sleep(20000);
                        if (cnt < 30)
                        {
                            stayinLoop = false;
                            DoWork(item);
                        }
                    }
                }
            }

Do work in a separate thread, so that sleep doesn't block you, could be a background worker , Begin , End method of webrequest or optionally an async task or Task.Run()

function DoWork()
//Do work in a sep thread.
cnt--;
)
查看更多
我想做一个坏孩纸
4楼-- · 2019-01-24 06:26

Use Thread.Sleep (from System.Threading):

for(int i = 0 ; i<64;i++)
{
     if(i % 8 == 0)
        Thread.Sleep(1000);
}
查看更多
对你真心纯属浪费
5楼-- · 2019-01-24 06:28

If you want a sleep after each 8 iterations, try this:

for (int i = 0; i < 64; i++)
{
    //...
    if (i % 8 == 7)
        Thread.Sleep(1000); //ms
}
查看更多
我欲成王,谁敢阻挡
6楼-- · 2019-01-24 06:36

There are a lot of ways to do that:

  • Method one: Criminally awful: Busy-wait:

    DateTime timeToStartUpAgain = whatever;

    while(DateTime.Now < timeToStartUpAgain) {}

This is a horrible thing to do; the operating system will assume that you are doing useful work and will assign a CPU to do nothing other than spinning on this. Never do this unless you know that the spin will be only for a few microseconds. Basically when you do this you've hired someone to watch the clock for you; that's not economical.

  • Method two: Merely awful: Sleep the thread.

Sleeping a thread is also a horrible thing to do, but less horrible than heating up a CPU. Sleeping a thread tells the operating system "this thread of this application should stop responding to events for a while and do nothing". This is better than hiring someone to watch a clock for you; now you've hired someone to sleep for you.

  • Method three: Break up the work into smaller tasks. Create a timer. When you want a delay, instead of doing the next task, make a timer. When the timer fires its tick event, pick up the list of tasks where you left off.

This makes efficient use of resources; now you are hiring someone to cook eggs and while the eggs are cooking, they can be making toast.

However it is a pain to write your program so that it breaks up work into small tasks.

  • Method four: use C# 5's support for asynchronous programming; await the Delay task and let the C# compiler take care of restructuring your program to make it efficient.

The down side of that is of course C# 5 is only in beta right now.

NOTE: As of Visual Studio 2012 C# 5 is in use. If you are using VS 2012 or later async programming is available to you.

查看更多
混吃等死
7楼-- · 2019-01-24 06:38

You may also want to just look into using a Timer rather than pausing the current thread in a loop.

It will allow you to execute some block of code (repeatedly or not) after an interval of time. Without more context it would be hard to say for sure if that's best in your situation or how you would go about altering your solution accordingly.

查看更多
登录 后发表回答