因此,此应用程序在Visual Studio中无缝运行,但我已为遇到错误的程序创建了一个安装程序。我想我已经确定了问题所在。当收到POST时,它会被处理,从而启动一个单独的解耦过程,该过程最终会从网页处理/关闭中止。
程序流程是这样的
context.Request.HttpMethod == "POST"
,csfireEyeHandler.DonJobOnLastIp()
,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;
}
}
答案 0 :(得分:0)
除非您的应用程序知道此Monitor并且知道如何检测其当前正在处理文件更改事件而不是从帖子返回,否则您无能为力。我建议不要将Web应用程序耦合到此Monitor(您没有解释其用途)。我建议将其从Web应用程序中取出并将其放入某种Windows服务中。或者,更详细地解释为什么此监视器位于Web应用程序中。
答案 1 :(得分:0)
第一个问题是,FileSystemWatcher
可以在创建文件时立即触发,这通常可以是,而ASP.NET进程仍处于写入过程中文件。
我希望这会导致XML读取异常或访问被拒绝的异常,但不一定是ThreadAbort
异常。 ThreadAbort
例外情况通常只有在有人致电Thread.Abort
时才会发生,而您永远不会这样做。
无论如何,您可以通过使用System.IO.FileStream
来编写文件并告诉窗口在写入文件时将其锁定来解决这个问题。
当您打开文件进行编写时,请指定FileShare.None
。这将阻止监视器在ASP.net进程完成写入之前尝试读取文件。
在您的监视器中,打开文件时添加一个小睡眠的重试循环。您应该反复获取访问被拒绝的异常(我认为这将是IOException
),直到文件准备好您阅读。
如果不了解你的csFireEyeHandler应该做什么,我真的无法帮助。您是否希望监视服务在ASP.net请求中完成处理文件?这不太可能发生。
我期望工作流程:
ASP PAGE Monitor Process > File Uploaded | | | > Begin Write to disk | | > Try open file | > fail to read file and retry > Finish write to disk | | > open file | | | > Begin process file > csFireEyeHandler.Load | > csFireEyeHandler.DonJob | > RETURN | | > Finish process file (Report.CreateReport)
如果实际上你需要fireEyeHandler来等待后台服务,有几种方法可以做到这一点......但为什么不在fireEyeHandler中处理文件?
答案 2 :(得分:0)
根据我对您的问题的解释,您不希望在将响应发送到客户端之前等到文件监视器事件发生。您想立即发送200并在后台处理。
这是ASP.NET中的反模式,因为当所有正在运行的HTTP请求都退出时,运行时不保证工作进程保持活动状态。从这个意义上讲,ASP.NET符合规范:它可以随时中止您的自定义线程。
如果您在发送200作为HTTP响应之前等待“服务处理”完成,那么更容易做到这一点。