2

好的,所以我一直在玩 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 毫秒的差异。我错过了什么?

4

5 回答 5

3

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

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

您可以阅读有关实时操作系统的信息以获取更多信息。

于 2011-04-05T20:13:15.183 回答
1

实施建议:如果您需要计时精度,而不是线程内的 Do/Loop(Thread.SleepSystem.Timers.Timer)。TimeSpan这将允许您在方法调用之间指定。

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

于 2011-04-05T20:15:23.980 回答
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
于 2011-04-05T20:17:47.427 回答
0

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

于 2011-04-05T20:28:48.490 回答
0

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

您对 DateTime.Now 和 DateTime.Now.Millisecond 的调用很可能会相隔近一秒(尤其是在两者之间进行一些垃圾收集的情况下)。

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

Dim dt as DateTime
dt = DateTime.Now
objWriter.Write(intTemp & " " & dt & " " & dt.Millisecond & vbCrLf)
于 2011-04-05T20:41:41.013 回答