VB.net不一致线程睡眠计时器

VB.net不一致线程睡眠计时器,.net,vb.net,sleep,thread-sleep,.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

好的,所以我一直在玩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行并进行减法运算会得到4958毫秒的差值。所以我的问题是那里到底发生了什么?当我告诉线程在完成进程之前休眠5000毫秒时,怎么可能得到小于5000毫秒的差异呢。我遗漏了什么?

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

第二,记住会有一些延迟,如果底层框架、操作系统和其他相关的设置设置为5000毫秒,那么您的代码永远不会在5000毫秒时触发,并且总是在5000毫秒后触发x毫秒。您所观察到的很可能是操作系统保留了一些关于平均延迟的记录,并相应地调整超时值,以尝试平均接近5000毫秒


您可以阅读更多信息。

实现建议:如果您需要计时精度,而不是线程内部的Do/Loop(使用
thread.Sleep
),只需使用类的实例即可(这与.NET之前的旧WinForms“Timer”对象大不相同)。这将允许您在方法调用之间指定
TimeSpan


尽管如此,我不能保证
线程.Sleep
计时器
实例之间的“精确性”(我只是假设
计时器
会更精确,因为计时是它的主要功能)。。。但是也许有人可以编写一个快速测试?

你还必须考虑实例化、打开和关闭一个新的流写器所需的时间。如果你在循环之外这样做,结果会更接近你的预期

例如:

  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

也许你的系统时钟在循环的中间被更新了。

< P>你的连接答案真的很简单。不能保证两条语句将在同一时间片中执行。因为在一条语句中有多个调用,所以情况更糟

很可能您对DateTime.Now和DateTime.Now.millished的调用可能相隔近一秒(特别是在这两者之间进行垃圾收集的情况下)

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

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

我猜操作系统会在5秒之前安排线程再次运行。听起来没那么糟糕。对,我唯一关心的是计时问题是,我将从一个也计时的外部源收集数据。如果最后我的计时器出现漂移,我有可能丢失数据点。你是对的,从更大的意义上说,它似乎完成了它被要求做的事情,即使个别时间差不是完美的。
Thread.Sleep通常不适合于计时任务。考虑这仍然不能保证一切,可能需要更高级的方法(ext.lib)或自旋等待。另外,请确保执行时间是从
x=start+i*m
计算的,而不是从
x+=m
计算的,因为后者在许多情况下都会引入错误,如上例所示。使用一个谨慎的公式,它总是能够调整回来。你应该在你的问题中添加这个测试是在虚拟机上运行的事实。我让您的测试运行了10分钟,但无法在Windows7上重现结果。@Seth Reno-谢谢您的提示,我将永远记住这一点。此外,非常感谢您花时间运行此测试10分钟!当然,您不必只在它运行时执行此操作,但是您需要花费一些时间来查看生成的文件。再次感谢!这是我在这里的第一个问题,每个人都非常乐于助人!问一个有趣的问题:Windows(比如7/2008)中的
Thread.Sleep
是否保证了不被中断的最短睡眠时间?当然不能保证最大值。我会猜到这是传递给
线程.睡眠
(例如,仅限超龄取整)的时间。虽然理论上我确信存在一些最低保证,但如果大量记录,我会感到惊讶。简单地说,任何依赖操作系统在毫秒级上维护任何保证的人要么是错误地处理了问题,要么是试图以一种非预期的方式使用操作系统。无论如何,这不会阻止任何人以某种最小值编码,因为显然可以确定过期的毫秒数,并且没有什么可以阻止开发人员在必要时将其重新投入睡眠模式。但是这不会导致更长的时间吗,现在缩短时间?这是假设您可以在文件上保持文件锁定,而不会受到试图访问它的其他程序的任何影响。同意这里的SpikeX。更好的方法是简单地将所有这些行保存到字符串生成器中,这只需要很少的处理时间。循环完成后,打开文件并写出字符串生成器的全部内容。谢谢,我真的没有想到这一点。我假设时间是由于磁盘IO子系统争夺资源造成的