3

人がページをロードするたびに、いくつかの統計をテキスト ファイルに書き込みたいと考えています。しかし、時々、「ファイルを開けませんでした。既に使用されています」というタイプのエラーが発生します。このエラーを 100% 再現することはできません。非常に不安定です。私のコードは

Public Sub WriteStats(ByVal ad_id As Integer)
    Dim ad_date As String = Now.Year & Now.Month

    Dim FILENAME As String = Server.MapPath("text/BoxedAds.txt")
    Dim objStreamWriter As StreamWriter
    objStreamWriter = File.AppendText(FILENAME)
    objStreamWriter.WriteLine(ad_id & ";" & ad_date)
    objStreamWriter.Close()
End Sub

私の質問は、ファイルをロックおよびロック解除して、不規則なエラーが発生しないようにするにはどうすればよいですか?

ありがとう

4

4 に答える 4

4
Public Sub WriteStats(ByVal ad_id As Integer)
    Dim ad_date As String = Now.Year & Now.Month
    Dim FILENAME As String = Server.MapPath("text/BoxedAds.txt")
    Dim index As Integer

    Using fs As New IO.FileStream(FILENAME, IO.FileMode.Append, IO.FileAccess.Write, IO.FileShare.ReadWrite), _
          tl As New TextWriterTraceListener(fs)

        index = Trace.Listeners.Add(tl)
        Trace.WriteLine(ad_id & ";" & ad_date)
        Trace.Listeners(index).Flush()
        Trace.Flush()
    End Using
    Trace.Listeners.RemoveAt(index)
End Sub

ここで重要なことは次の 3 つです。

  1. IO.FileShare.ReadWrite を使用して、一度に複数の書き込みをファイルに許可します。
  2. 例外が発生した場合でも、ストリームがすぐに閉じられるようにする Using ステートメント。これにより、衝突が最小限に抑えられます
  3. TextWriterTraceListener は、要求されたファイルを開けない場合、メッセージが失われないように一時ファイルを作成します。
于 2009-03-12T16:31:13.130 に答える
4

2 つ以上のリクエストがほぼ同時に Web サーバーに到達すると、それらはすべて同じファイルを開こうとします。リクエストごとに一意のファイル名を作成する必要があります。

于 2009-03-12T16:23:52.853 に答える
1

例外を処理し、短いランダム間隔の後にファイルへの書き込みを再試行するための処理を構築する必要があります。

競合が多すぎる場合は、それをデータベースのテーブルに記録し、ファイルにエクスポートするプロセスを作成する方が理にかなっています (まだ必要な場合)。

于 2009-03-12T16:28:36.430 に答える
0

File.AppendAllText(path, info); を使用して短い情報に問題はありませんでした。

ロックの原因となるコメントについては、リフレクターから Joel によって非常によく説明されているのと同じオプションを使用します。トレースライタを使用しないため、高負荷・大容量でトラブルが発生した場合に一時ファイルに出力しません。

情報が大きい場合は、本当に別のファイルが必要です。負荷が高い場合は、Joel の提案に従い、一時ファイルを作成します。代わりに、File.AppendAllText で例外をキャッチし、同じ File.AppeandAllText を一意のファイル名で使用します。

于 2009-03-12T16:29:43.727 に答える