我的项目(C#,VS2010,.NET 4.0)要求特定的for
循环必须在200毫秒内完成。如果没有那么它必须在此持续时间之后终止而不执行剩余的迭代。循环通常为i = 0
至约500,000至700,000,因此总循环时间变化。
我读过以下类似的问题,但在我的案例中没有帮助:
到目前为止,我已尝试使用Stopwatch
对象来跟踪已用时间,但它对我不起作用。到目前为止,我尝试了两种不同的方法:
方法1。比较for
循环中的已用时间:
Stopwatch sw = new Stopwatch();
sw.Start();
for (i = 0; i < nEntries; i++) // nEntries is typically more than 500,000
{
// Do some stuff
...
...
...
if (sw.Elapsed > TimeSpan.FromMilliseconds(200))
break;
}
sw.Stop();
这不起作用,因为if (sw.Elapsed > TimeSpan.FromMilliseconds(200))
需要超过200毫秒才能完成。因此在我的情况下毫无用处。我不确定TimeSpan.FromMilliseconds()
是否通常需要这么长时间,或者仅仅因为某些原因而在我的情况下。
方法2。创建一个单独的线程来比较时间:
Stopwatch sw = new Stopwatch();
sw.Start();
bool bDoExit = false;
int msLimit = 200;
System.Threading.ThreadPool.QueueUserWorkItem((x) =>
{
while (bDoExit == false)
{
if (sw.Elapsed.Milliseconds > msLimit)
{
bDoExit = true;
sw.Stop();
}
System.Threading.Thread.Sleep(10);
}
});
for (i = 0; i < nEntries; i++) // nEntries is typically more than 500,000
{
// Do some stuff
...
...
...
if (bDoExit == true)
break;
}
sw.Stop();
我在for循环中有一些其他代码可以打印一些统计信息。它告诉我,在方法2的情况下,for
循环在完成所有迭代之前肯定会中断,但循环时间仍然是280-300毫秒。
在200毫秒或更短时间内严格打破for循环的任何建议? 感谢。
答案 0 :(得分:6)
为了更快的比较,请尝试比较
if(sw.ElapsedMilliseconds > 200)
break;
你应该检查循环的开始以及处理过程中(“//做一些东西”代码的一部分),因为例如,处理可以从190开始(开始时)循环),持续20,结束于210。
您还可以测量处理的平均执行时间(这是近似的,因为它依赖于平均时间),这种方式循环应该持续200毫秒或更短,这是一个可以放在控制台的Main方法中的演示应用程序并根据您的应用轻松修改它:
Stopwatch sw = new Stopwatch();
sw.Start();
string a = String.Empty;
int i;
decimal sum = 0, avg = 0, beginning = 0, end = 0;
for (i = 0; i < 700000; i++) // nEntries is typically more than 500,000
{
beginning = sw.ElapsedMilliseconds;
if (sw.ElapsedMilliseconds + avg > 200)
break;
// Some processing
a += "x";
int s = a.Length * 100;
Thread.Sleep(19);
/////////////
end = sw.ElapsedMilliseconds;
sum += end - beginning;
avg = sum / (i + 1);
}
sw.Stop();
Console.WriteLine(
"avg:{0}, count:{1}, milliseconds elapsed:{2}", avg, i + 1,
sw.ElapsedMilliseconds);
Console.ReadKey();
答案 1 :(得分:1)
使用第一个 - 简单,比第二个更精确的机会。
两种情况都有相同的终止条件,因此两者的行为大致相同。第二个是由于线程和睡眠的使用而复杂得多,所以我先使用第一个。由于睡眠,第二个也不太准确。
TimeSpan.FromMilliseconds(200)
绝对没有理由花费任何大量时间(以及在每次迭代中调用它)。
答案 2 :(得分:1)
另一种选择是使用CancellationTokenSource:
CancellationTokenSource source = new CancellationTokenSource(100);
while(!source.IsCancellationRequested)
{
// Do stuff
}
答案 3 :(得分:0)
我不知道这是不是确实如此,但我认为使用System.Timers.Timer
值得一试:
int msLimit = 200;
int nEntries = 500000;
bool cancel = false;
System.Timers.Timer t = new System.Timers.Timer();
t.Interval = msLimit;
t.Elapsed += (s, e) => cancel = true;
t.Start();
for (int i = 0; i < nEntries; i++)
{
// do sth
if (cancel) {
break;
}
}
答案 4 :(得分:0)
使用取消令牌:
var cancellationToken = new CancellationTokenSource(TimeSpan.FromSeconds(15)).Token;
while (!cancellationToken.IsCancellationRequested)
{
//Do stuff...
}