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 (with Thread.Sleep) の代わりに、クラスのインスタンスを使用するだけですSystem.Timers.Timer(これは、.NET 以前の古い WinForms "Timer" オブジェクトとは大きく異なります)。 )。これTimeSpanにより、メソッド呼び出しの間を指定できます。

Thread.Sleepただし、インスタンスとインスタンスの間の真の「精度」を保証することはできません(タイムキーピングがその主な機能であることを考えるとTimer、a の方が正確であると想定しました) ... しかし、おそらく誰かが簡単なテストを作成できますか?Timer

于 2011-04-05T20:15:23.980 に答える
0

あなたの難問への答えは本当に簡単です。2つのステートメントが同じタイムスライスで実行されるという保証はありません。1つのステートメントに複数の呼び出しがあるため、さらに悪いことになります。

DateTime.NowとDateTime.Now.Millisecondの呼び出しは、ほぼ1秒間隔で発生する可能性があります(特に、その間にガベージコレクションが行われている場合)。

それがあなたの問題だと言っているのではありませんが、書かれているようにその可能性は存在します。時間を変数に取り込むことで、その可能性を回避できます。

Dim dt as DateTime
dt = DateTime.Now
objWriter.Write(intTemp & " " & dt & " " & dt.Millisecond & vbCrLf)
于 2011-04-05T20:41:41.013 に答える
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 に答える