VB.net Inconsistant Thread Sleep Timer

谁说我不能喝 提交于 2020-01-04 06:08:05

问题


Ok so I have been playing with VB.net and brainstorming ways to accomplish launching a thread reliably every 60 seconds reguardless of how long the prior thread took to do it's work. Here is my question. Given the following code:

    Dim intTemp As Integer
    intTemp = 2
    Do While intTemp > 1
        Dim objWriter As New System.IO.StreamWriter("C:\Documents\Visual Studio 2010\Projects\Report\Report\Stream.txt", True)
        intTemp = intTemp + 1
        System.Threading.Thread.Sleep(5000)

        objWriter.Write(intTemp & " " & Date.Now & " " & Date.Now.Millisecond & vbCrLf)
        objWriter.Close()
    Loop

Produces this in the stream.txt file.

3 4/5/2011 9:41:27 AM 807
4 4/5/2011 9:41:32 AM 812
5 4/5/2011 9:41:37 AM 817
6 4/5/2011 9:41:42 AM 822
7 4/5/2011 9:41:47 AM 826
8 4/5/2011 9:41:52 AM 831
9 4/5/2011 9:41:57 AM 836
10 4/5/2011 9:42:02 AM 841
11 4/5/2011 9:42:07 AM 799

My assumption for this output would be that the time between each line would have to be exactly 5000 milliseconds plus the time it takes to execute the rest of the loop which could vary given that there could be an unknown delay due to disk IO. My problem is that looking at lines 10 and 11 and subtracting gives me a difference of 4,958 milliseconds. So my question is what the heck is going on there? How is it possible to get a difference of less than 5000 milliseconds when I have told the thread to sleep for 5000 milliseconds before completing the process. What am I missing?


回答1:


Implementation Suggestion: If you need timing precision, instead of a Do/Loop inside of a thread (with Thread.Sleep), just use an instance of the System.Timers.Timer class (this is very different from the old WinForms "Timer" object back in pre-.NET days). This will let you specify a TimeSpan between method calls.

Although, I can't vouch for true "precision" between Thread.Sleep vs. a Timer instance (I just assumed a Timer would be more accurate, given that Timekeeping is its primary function)... but perhaps someone could write up a quick test?




回答2:


First, understand that all major operating systems, especially those with multitasking capabilities will never be capable of landing timers down to the millisecond. The architecture simply doesn't support it.

Second, with the idea in mind that there will be some delay, if a setting of 5000 milliseconds were set by the underlying frameworks, operating system and whatever else is involved your code would never fire at 5000 milliseconds and always some x number of milliseconds after. What you're observing is most likely the operating system keeping some record as to the average delay and adjusting the timeout value accordingly in an attempt to land closer to 5000 milliseconds on average.

You can read about real time operating systems to get more information.




回答3:


Maybe your system clock was updated in the middle of the loop.




回答4:


You also have to consider the time that it takes to instantiate, open & close a new StreamWriter. If you do this outside of the loop the results will be much closer to what you expect.

For example:

  Dim builder As New Text.StringBuilder()
  For i As Integer = 0 To 10
    Threading.Thread.Sleep(1000)
    builder.AppendLine(String.Format("{0} {1} {2}", i, Now, Now.Millisecond))
  Next
  IO.File.WriteAllText("c:\sleepTest.txt", builder.ToString)

Produces this output:

0 4/5/2011 3:15:35 PM 974
1 4/5/2011 3:15:36 PM 988
2 4/5/2011 3:15:37 PM 988
3 4/5/2011 3:15:38 PM 988
4 4/5/2011 3:15:39 PM 989
5 4/5/2011 3:15:40 PM 989
6 4/5/2011 3:15:41 PM 989
7 4/5/2011 3:15:42 PM 989
8 4/5/2011 3:15:43 PM 989
9 4/5/2011 3:15:44 PM 989
10 4/5/2011 3:15:45 PM 989



回答5:


The answer to your connundrum is pretty simple really. There is no guarantee that two statements will execute in the same time slice. Because you have multiple calls in a single statement, it's even worse.

It's quite possible that your call to DateTime.Now and DateTime.Now.Millisecond could occur nearly a second apart (particularly if some garbage collection were going on in between).

I'm not saying that IS your problem, but as written that possibility exists. You can avoid that possibility by capturing the time in a variable.

Dim dt as DateTime
dt = DateTime.Now
objWriter.Write(intTemp & " " & dt & " " & dt.Millisecond & vbCrLf)


来源:https://stackoverflow.com/questions/5557817/vb-net-inconsistant-thread-sleep-timer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!