làm cách nào tôi có thể sử dụng thời gian trễ trong vòng lặp sau khi xoay vòng nhất định? Giả sử:Thời gian trễ trong vòng lặp trong C#
for(int i = 0 ; i<64;i++)
{
........
}
tôi muốn trì hoãn 1 giây sau mỗi vòng xoay 8 giây.
làm cách nào tôi có thể sử dụng thời gian trễ trong vòng lặp sau khi xoay vòng nhất định? Giả sử:Thời gian trễ trong vòng lặp trong C#
for(int i = 0 ; i<64;i++)
{
........
}
tôi muốn trì hoãn 1 giây sau mỗi vòng xoay 8 giây.
Có rất nhiều cách để làm điều đó:
Phương pháp một: hình sự khủng khiếp: Bận-wait:
DateTime timeToStartUpAgain = whatever;
while(DateTime.Now < timeToStartUpAgain) {}
Đây là một điều khủng khiếp để làm; hệ điều hành sẽ cho rằng bạn đang làm công việc hữu ích và sẽ chỉ định một CPU để không làm gì khác ngoài việc quay về điều này. Không bao giờ làm điều này trừ khi bạn biết rằng spin sẽ chỉ trong vài micro giây. Về cơ bản khi bạn làm điều này bạn đã thuê một người nào đó để xem đồng hồ cho bạn; đó không phải là kinh tế.
Ngủ một sợi cũng là một điều kinh khủng, nhưng ít kinh khủng hơn là làm nóng CPU. Ngủ một thread cho hệ điều hành "thread này của ứng dụng này nên ngừng đáp ứng với các sự kiện trong một thời gian và không phải làm gì". Điều này tốt hơn việc thuê một người nào đó để xem đồng hồ cho bạn; bây giờ bạn đã thuê một người nào đó để ngủ cho bạn.
Điều này giúp sử dụng hiệu quả tài nguyên; bây giờ bạn đang thuê một người nào đó để nấu trứng và trong khi những quả trứng đang nấu ăn, họ có thể làm bánh mì nướng.
Tuy nhiên, thật khó để viết chương trình của bạn để nó chia nhỏ công việc thành các tác vụ nhỏ.
Mặt trái của khóa học là tất nhiên C# 5 hiện chỉ có bản beta.
LƯU Ý: Kể từ khi Visual Studio 2012 C# 5 đang được sử dụng. Nếu bạn đang sử dụng VS 2012 hoặc chương trình không đồng bộ sau này có sẵn cho bạn.
Sử dụng Thread.Sleep (từ System.Threading):
for(int i = 0 ; i<64;i++)
{
if(i % 8 == 0)
Thread.Sleep(1000);
}
Nếu bạn muốn có một giấc ngủ sau mỗi 8 lần lặp lại, cố gắng này:
for (int i = 0; i < 64; i++)
{
//...
if (i % 8 == 7)
Thread.Sleep(1000); //ms
}
Bạn cũng có thể muốn chỉ cần nhìn vào cách sử dụng một Timer
thay vì tạm dừng luồng hiện tại trong một vòng lặp.
Nó sẽ cho phép bạn thực hiện một số khối mã (nhiều lần hoặc không) sau một khoảng thời gian. Nếu không có nhiều ngữ cảnh thì sẽ khó có thể nói chắc chắn nếu đó là điều tốt nhất trong tình huống của bạn hay cách bạn sẽ thay đổi giải pháp của bạn cho phù hợp.
Đây là triển khai mà tôi đã đưa ra. Nó là chung chung, vì vậy bạn có thể dễ dàng tái sử dụng nó cho trường hợp sử dụng của bạn. (Nó gắn với những gì @Servy gợi ý)
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;
}
}
Và sau đó sử dụng nó như vậy:
var numbers = Enumerable.Range(1, 10).ToList();
var interval = 1000; // 1000 ms delay
numbers.ForEachWithDelay(i => Task.Run(() => Console.WriteLine(i + " @ " + DateTime.Now)), interval);
mà in này:
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
Hãy thử phiên bản này đơn giản hơn mà không phụ thuộc vào async hay đang chờ hoặc TPL.
Mã đây
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);
}
}
}
}
Làm việc trong một thread riêng biệt, vì vậy giấc ngủ mà không chặn bạn, có thể là nhân viên nền, Bắt đầu, Kết thúc phương thức yêu cầu web hoặc tùy chọn tác vụ không đồng bộ hoặc Task.Run()
function DoWork()
//Do work in a sep thread.
cnt--;
)
+1 cho cả hai câu trả lời, cũng sẽ chặn chuỗi giao diện người dùng nếu sử dụng sai. –
Điều đó sẽ ngủ sau lần lặp đầu tiên. – user7116