1

そのため、このアプリケーションはVisual Studioでシームレスに実行されますが、エラーが発生したプログラムのインストーラーを作成しました。私は問題が何であるかを特定したと思います。POSTが受信されると、POSTが処理され、個別の分離されたプロセスが開始され、最終的にWebページの破棄/クローズから中止されます。

プログラムの流れはこんな感じ

  • POSTを受信しましたcontext.Request.HttpMethod == "POST"
  • 抽出されてディスクに書き込まれた関連するxml情報、
  • csfireEyeHandler.DonJobOnLastIp()
  • バックグラウンドで実行されているモニターは、ファイル作成イベント `void OnChanged'を検出し、XMLドキュメントに基づいてサービスの実行を開始します
  • FileAdded-> readerRef.ReadInServices(e.FullPath, false)

問題は、POSTが処理された後、サービスがThreadAbortExceptionで中止されることです。handler.ProcessRequest(context)サービス終了後に遅れる場合は、まだページが開いていると思います。この状況を適切に処理する方法がわかりません。VSでエラーが発生しないため、デバッグが非常に困難です。

public partial class fireEye : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        HttpContext context = Context;
        fireEyeHandler handler = new fireEyeHandler();
        handler.ProcessRequest(context);          
    }
}

public class fireEyeHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        if (context.Request.HttpMethod == "POST")
        {
            var extension = context.Request.Url.AbsolutePath.Split('/')[2].ToLower();

            var stream = context.Request.InputStream;
            var buffer = new byte[stream.Length];
            stream.Read(buffer, 0, buffer.Length);
            var xml = Encoding.UTF8.GetString(buffer);

            FileManage.WriteToFile(xml, @"C:\ECC_output\fireEye.xml");
            var csfireEyeHandler = new FireEyeService { config = extension + ".config" };

            csfireEyeHandler.Load();
            csfireEyeHandler.DonJobOnLastIp();

            context.Response.StatusCode = 202;              
        }
    }

    public bool IsReusable
    {
        get { return false; }
    }
}

public class Monitor
{
    bool monitorIsActive;
    readonly XmlRead readerRef;  // Reference to the xml reader
    readonly FileSystemWatcher watch;
    public bool monitorRunning;

    public Monitor(XmlRead reader)
    {
        watch = new FileSystemWatcher();
        readerRef = reader;

        try
        {
            watch.Path = @"C:\ECC_temp"; //directory to monitor
        }
        catch (ArgumentException ex)
        {
            Report.LogLine (ex.Message);
            return;
        }

        watch.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;

        watch.Filter = "*.xml";
        monitorIsActive = true;

        watch.Created += OnChanged;
        watch.Deleted += OnChanged;
        watch.Renamed += OnRenamed;

        watch.EnableRaisingEvents = true;
    }

    /// <summary>
    /// Toggles on/off if a directory is being monitored
    /// </summary>
    public void ToggleMonitor()
    {
        monitorIsActive = !monitorIsActive;
        var monitorState = monitorIsActive ? "on" : "false";

        Report.LogLine ("Monitor is " + monitorState);
    }

    /// <summary>
    /// File has been added to the directory
    /// </summary>
    public bool FileAdded(FileSystemEventArgs e, XmlDocument xmlDocument)
    {
        try
        {
            var date = string.Format ("<br>\r\n**********************Report  {0:yyyy MM-dd hh:mm tt}**********************", DateTime.Now);
            Report.LogLine(date);

            readerRef.Validate(e.FullPath, false);
            readerRef.ReadInServices(e.FullPath, false);

            Report.CreateReport();
        }
        catch (Exception exception)
        {
            Report.LogLine(exception.Message + " id:6");
            Report.CreateReport();
            return true;
        }
        return true;
    }

    /// <summary>
    /// When a file is added, renamed or deleted, OnChanged is called and the appropriate action is taken
    /// </summary>
    private void OnChanged(object source, FileSystemEventArgs e)
    {
        monitorRunning = true;
        while (true)
        {
            if (e.ChangeType == WatcherChangeTypes.Created || e.ChangeType == WatcherChangeTypes.Renamed)
            {
                var xmlDocument = new XmlDocument();
                try
                {                        
                    xmlDocument.Load(e.FullPath);
                }
                catch (IOException)
                {
                    Thread.Sleep(100);
                }

                if (FileAdded(e, xmlDocument))
                {
                    break;
                }
            }

        }
        monitorRunning = false;
    }
}
4

3 に答える 3

0

私の質問の解釈によると、クライアントに応答を送信する前に、ファイルモニターイベントが発生するまで待ちたくありません。200をすぐに送信し、バックグラウンドで処理したいとします。

これはASP.NETのアンチパターンです。これは、実行中のすべてのHTTP要求が終了したときに、ランタイムがワーカープロセスが存続することを保証しないためです。その意味で、ASP.NETは仕様に準拠しています。カスタムスレッドはいつでも中止できます。

「サービス処理」が完了するまで待ってから200をHTTP応答として送信すると、これを正しく行うのが簡単になります。

于 2012-07-19T22:47:56.803 に答える
0

最初の問題は、ファイルが作成さFileSystemWatcherれるとすぐに発生する可能性があることです。これは、多くの場合、ASP.NET プロセスがまだドキュメントを書き込んでいる間に発生する可能性があります。

これにより、XML 読み取り例外またはアクセス拒否例外が発生すると予想されますが、必ずしも例外ではありませんThreadAbortThreadAbort例外は通常、誰かが を呼び出しThread.Abortた場合にのみ発生しますが、これは決して行うべきではありません。

とにかく、 を使用System.IO.FileStreamしてファイルを書き込み、書き込み中にウィンドウをロックするように指示することで、これを回避できます。

  • ファイルを開いて書き込む場合は、 を指定しますFileShare.None。これにより、ASP.net プロセスが書き込みを完了するまで、モニターがファイルを読み取ろうとしなくなります。

  • モニターで、ファイルを開くときに小さなスリープを含む再試行ループを追加します。IOExceptionファイルを読み取る準備が整うまで、アクセス拒否例外 (これは になると思います) が繰り返し発生するはずです。

csFireEyeHandler が何をすべきかを理解していなければ、それ以上のことはできません。ASP.net 要求の途中で監視サービスがファイルの処理を終了することを期待していますか? これが起こる可能性は低いです。

私が期待するワークフローは次のとおりです。

         ASP PAGE モニター プロセス

     > ファイルがアップロードされました |
     | | | |
     > ディスクへの書き込みを開始 |
     | | > ファイルを開いてみる
     | | > ファイルの読み取りに失敗し、再試行します
     > ディスクへの書き込みを終了 |
     | | > ファイルを開く
     | | | |
     | | > 処理開始ファイル
     > csFireEyeHandler.Load |
     > csFireEyeHandler.DonJob |
     > 戻る |
                                       | |
                                       > 処理ファイルの終了 (Report.CreateReport)

実際にバックグラウンド サービスを待機するために fireEyeHandler が必要な場合、これを行う方法はいくつかありますが、fireEyeHandler でファイルを処理するだけではどうですか?

于 2012-07-19T21:02:44.143 に答える
0

アプリケーションがこのモニターについて認識しており、現在ファイル変更イベントを処理していることを検出し、ポストから戻らない方法を認識していない限り、何もできません。Web アプリケーションをこのモニターに結合しないことをお勧めします (その目的を説明していません)。Web アプリケーションから取り出して、何らかの Windows サービスに配置することをお勧めします。または、このモニターが Web アプリケーションにある理由を詳しく説明してください。

于 2012-07-19T20:30:39.837 に答える