1

asp.netmvcに非同期書き込みログが必要です 。コードは次のようになります。

public ActionResult Index()
        {
            byte[] buffer = Encoding.UTF8.GetBytes(string.Format("log:{0}{1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff"), Environment.NewLine));
            FileStream fs = new FileStream(@"c:\log.txt", FileMode.Append, FileAccess.Write, FileShare.Write, 1024, true);
            fs.BeginWrite(buffer, 0, buffer.Length, ar =>
              {
                  fs.EndWrite(ar);
                  fs.Close();
              }, null);
         }

しかし、結果は私が期待したものではなく、一部のログが記録されていません、誰かがコードの何が問題になっているのか教えてもらえますか

4

1 に答える 1

7

1つのスレッドだけがファイルに書き込んでいることを確認する必要があります。2人の同時ユーザーが同時にインデックスアクションを呼び出している場合、それらは同時にログファイルに書き込もうとし、2番目は失敗する可能性があります。ASP.NETなどのマルチスレッドアプリケーションでは、共有リソースへのアクセスを適切に同期していることを常に確認してください。

また、あなたのコードでは、エラーを防いでいません。例外がスローされた場合はどうなりますか?このストリームを閉じることは決してなく、2回目のアクセスの試みは例外をスローします。

したがって、このコードを単純化する1つの可能性は、TPLを使用することです。

private static object _synRoot = new object();

public ActionResult Index()
{
    Task.Factory.StartNew(() =>
    {
        lock (_synRoot)
        {
            var data = string.Format("log:{0}{1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff"), Environment.NewLine)
            System.IO.File.AppendAllText("log.txt", data);
        }
    });
    return View();
}

また、コントローラーでのこのようなノイズや汚染を回避するために、アクションフィルターを使用できます。

public class LogAttribute : ActionFilterAttribute
{
    private static object _synRoot = new object();

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Task.Factory.StartNew(() =>
        {
            lock (_synRoot)
            {
                var data = string.Format("log:{0}{1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ffff"), Environment.NewLine)
                System.IO.File.AppendAllText(@"log.txt", data);
            }
        });
    }
}

その後:

[Log]
public ActionResult Index()
{
    return View();
}

ただし、ホイールを再発明する代わりに、.NETFrameworkに組み込まれているトレース機能を使用することをお勧めします。

于 2012-04-19T06:01:48.463 に答える