VB.net Inconsistant线程睡眠定时器

时间:2011-04-05 20:05:36

标签: .net vb.net sleep thread-sleep

好的,所以我一直在玩VB.net并集思广益,每隔60秒就可以完成一次可靠的启动线程,无论前一个线程花多长时间完成它的工作。这是我的问题。给出以下代码:

    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

在stream.txt文件中生成此内容。

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

我对此输出的假设是每行之间的时间必须精确到5000毫秒加上执行剩余循环所需的时间,这可能会因为磁盘IO可能存在未知延迟而有所不同。我的问题是看第10行和第11行并减去给我4,958毫秒的差异。所以我的问题是那里到底发生了什么?当我告诉线程在完成该过程之前休眠5000毫秒时,怎么可能得到小于5000毫秒的差异。我错过了什么?

5 个答案:

答案 0 :(得分:3)

首先,要了解所有主要操作系统,尤其是具有多任务处理能力的操作系统,永远无法将计时器降至毫秒级。该架构根本不支持它。

其次,考虑到会有一些延迟,如果底层框架,操作系统和其他任何涉及的设置为5000毫秒,您的代码将从不触发5000毫秒,总是在x毫秒之后。你观察到的最有可能是操作系统保留一些关于平均延迟的记录并相应地调整超时值,以试图平均接近5000毫秒。

您可以阅读real time operating systems以获取更多信息。

答案 1 :(得分:1)

实现建议:如果你需要时间精度,而不是一个线程内的Do / Loop(带Thread.Sleep),只需使用System.Timers.Timer类的一个实例(这与旧的WinForms“Timer”对象早于.NET时代。这将允许您在方法调用之间指定TimeSpan

虽然,我无法保证Thread.SleepTimer实例之间的真正“精确度”(我假设Timer会更准确,因为Timekeeping是它的主要功能)......但也许有人可以写一个快速测试?

答案 2 :(得分:0)

您还必须考虑实例化,打开和播放所需的时间。关闭一个新的StreamWriter。如果您在循环外执行此操作,结果将更接近您的预期。

例如:

  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)

生成此输出:

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

答案 3 :(得分:0)

也许您的系统时钟已在循环中间更新。

答案 4 :(得分:0)

你的connundrum的答案非常简单。无法保证两个语句将在同一时间片中执行。因为在一个语句中有多个调用,所以情况更糟。

您对DateTime.Now和DateTime.Now.Millisecond的调用很可能会在几秒钟内发生(特别是如果之间正在进行一些垃圾收集)。

我不是说这是你的问题,但正如所写,这种可能性存在。您可以通过捕获变量中的时间来避免这种可能性。

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