假设您有一个每100毫秒运行一次的代码块,但该块中的代码需要500毫秒才能运行。它是否完成了代码块的处理?
while (true)
{
System.Threading.Thread.Sleep(100);
OnTick();
}
public void OnTick(){ //Block of code that take 500 milliseconds to process }
答案 0 :(得分:7)
此代码不会每100毫秒运行一次,它会在每次迭代之间等待100毫秒。重要的区别。
您正在同步调用该代码,因此该循环的下一次迭代将在OnTick()
返回后发生。
现在,如果这是一个实际的计时器滴答(而不是Thread.Sleep()
),或者500毫秒的工作将在另一个线程上发生,这将会改变。
答案 1 :(得分:6)
你的循环每100毫秒不会运行500毫秒的代码块;它运行500毫秒的块,它们之间的延迟为100毫秒。每次迭代需要600毫秒:
您可以制作一段代码,每100毫秒启动一个新的代码块。如果代码占用500毫秒的CPU时间,则只要可用内核数量耗尽,系统就会过载。
另一方面,如果500毫秒块中的代码花费大部分时间在单独的线程中休眠或等待I / O,则系统将继续生成新线程,直到达到最大值,或者记忆力已经耗尽。
答案 2 :(得分:3)
这完全取决于OnTick()
的实现 - 如果它是同步的,并且不产生任何后台线程(等),那么你的循环将等待100ms,花费500ms运行OnTick()
,然后(并且只有这样)等待另一个100ms,然后再次运行OnTick()
答案 3 :(得分:0)
这意味着执行一个语句,然后执行下一个语句。
这意味着在您的示例中,代码等待100毫秒,然后它执行500毫秒的操作。
答案 4 :(得分:0)
while循环等待100毫秒,然后调用onTick()。因此,下一次迭代将在onTick()返回后发生。它是顺序的。
答案 5 :(得分:0)
正如其他人已经解释的那样,你的代码只是在另一个之后执行一个语句。
我认为实际的问题是如何在没有重叠执行的情况下每100毫秒运行一次。否则,您可以直接使用System.Threading.Timer。
一种选择是使用Task.Delay
在循环内异步等待100ms。
public async Task RunTimer(Action act,TimeSpan delay,CancellationToken token)
{
while(!token.IsCancellationRequested)
{
await Task.Delay(delay,token);
if (!token.IsCancellationRequested)
{
act();
}
}
}
取消令牌允许取消计时器。例如:
var cts=new CancellationTokenSource();
var delay=TimeSpan.FromMilliseconds(100);
var timerTask= RunTimer(()=>someMethod(),delay,cts.Token);
...
cts.Cancel();