C# 文件监视程序问题
好的,所以这次我创建了一个服务,其中包含一个文件观察程序,用于在创建文件后处理该文件 当正在处理的文件达到1000个时,我的服务似乎崩溃了,因为我收到了大量的消息 以下是我的逻辑:文件进入,文件观察者阅读文本,将其发送到电子邮件,插入数据库,将原始邮件移动到文件夹 在服务启动时,我先处理挂起的消息,然后再开始观看。我说的是1000多个文本文件挂起,我的服务需要大约一秒钟来处理每个文件 一切正常,但当传入的文件总数达到1000个时,它就会崩溃。 有时,服务停止处理挂起的文件,只开始查找新文件 我的InternalBufferSize=64000是建议的最大值 请帮助我编写代码我知道它应该是多线程的,以便更好地处理,但我不是专家:C# 文件监视程序问题,c#,file-watcher,C#,File Watcher,好的,所以这次我创建了一个服务,其中包含一个文件观察程序,用于在创建文件后处理该文件 当正在处理的文件达到1000个时,我的服务似乎崩溃了,因为我收到了大量的消息 以下是我的逻辑:文件进入,文件观察者阅读文本,将其发送到电子邮件,插入数据库,将原始邮件移动到文件夹 在服务启动时,我先处理挂起的消息,然后再开始观看。我说的是1000多个文本文件挂起,我的服务需要大约一秒钟来处理每个文件 一切正常,但当传入的文件总数达到1000个时,它就会崩溃。 有时,服务停止处理挂起的文件,只开始查找新文件 我的
protected override void OnStart(string[] args)
{
using(TREEEntities TEX = new TREEEntities())
{
var mp= TEX.TREE_settings.FirstOrDefault(x=>x.SET_key =="MSGDump");
MsgsPath = mp.SET_value;
var dc = TEX.TREE_settings.FirstOrDefault(x => x.SET_key == "DupCash");
DupCash = Convert.ToInt16(dc.SET_value);
}
if (Directory.Exists(MsgsPath))
{
if (!Directory.Exists(MsgsPath+"\\Archive"))
{
Directory.CreateDirectory(MsgsPath+"\\Archive");
}
if (!Directory.Exists(MsgsPath + "\\Duplicates"))
{
Directory.CreateDirectory(MsgsPath + "\\Duplicates");
}
if (!Directory.Exists(MsgsPath + "\\Unsent"))
{
Directory.CreateDirectory(MsgsPath + "\\Unsent");
}
}
else
{
Directory.CreateDirectory(MsgsPath);
Directory.CreateDirectory(MsgsPath + "\\Archive");
Directory.CreateDirectory(MsgsPath + "\\Duplicates");
Directory.CreateDirectory(MsgsPath + "\\Unsent");
}
processPending();//<--- process pending files after last service stop
fileSystemWatcher1.Path = MsgsPath;//<--- path to be watched
fileSystemWatcher1.EnableRaisingEvents = true;
fileSystemWatcher1.InternalBufferSize = 64000;
addToLog(DateTime.Now, "Service Started", 0, "Service", "Info");
addToLog(DateTime.Now, "File Watcher Started", 0, "Service", "Info");
//dupList.Clear();//<--- clear duplicates validation list
}
protected override void OnStop()
{
fileSystemWatcher1.EnableRaisingEvents = false;
addToLog(DateTime.Now, "File Watcher Stopped", 0, "Service", "Alert");
addToLog(DateTime.Now, "Service Stopped", 0, "Service", "Alert");
}
private void fileSystemWatcher1_Created(object sender, FileSystemEventArgs e)
{
try
{
//---------read from file------------
Thread.Sleep(200);//<---give the file some time to get released
string block;
using (StreamReader sr = File.OpenText(MsgsPath + "\\" + e.Name))
{
block = sr.ReadToEnd();
}
PRT = block.Substring(block.Length - 6, 6);//<--- get the printer name
seq = Convert.ToInt16(block.Substring(block.Length - 20, 20).Substring(0, 4));//<--- get the sequence number
switch (PRT)//<----track sequence number from the 3 printers
{
case "64261B"://<---prt1
int seqPlus1=0;
if(seqPrt1 == 9999)//<---ignore sequence change from 9999 to 1
{ seqPlus1 = 1; }
else { seqPlus1 = seqPrt1 + 1; }
if (seq != seqPlus1 && seqPrt1 != 0)//<---"0" to avoid first service start
{
int x = seq - seqPrt1 - 1;
for (int i = 1; i <= x; i++)
{
addToMissing(PRT, seqPlus1);
addToLog(DateTime.Now, "Missing Sequence Number On Printer: " + PRT + " - " + seqPlus1, seqPlus1, "Service", "Missing");
seqPlus1++;
}
seqPrt1 = seq;
}
else { seqPrt1 = seq; }
break;
case "24E9AA"://<---prt2
int seqPlus2=0;
if(seqPrt2 == 9999)
{ seqPlus2 = 1; }
if (seq != seqPlus2 && seqPrt2 != 0)
{
int x = seq - seqPrt2 - 1;
for (int i = 1; i <= x; i++)
{
addToMissing(PRT, seqPlus2);
addToLog(DateTime.Now, "Missing Sequence Number On Printer: " + PRT + " - " + seqPlus2, seqPlus2, "Service", "Missing");
seqPlus2++;
}
seqPrt2 = seq;
}
else { seqPrt2 = seq; }
break;
case "642602"://<---prt3
int seqPlus3=0;
if(seqPrt3 == 9999)
{ seqPlus3 = 1; }
if (seq != seqPlus3 && seqPrt3 != 0)
{
int x = seq - seqPrt3 - 1;
for (int i = 1; i <= x; i++)
{
addToMissing(PRT, seqPlus3);
addToLog(DateTime.Now, "Missing Sequence Number On Printer: " + PRT + " - " + seqPlus3, seqPlus3, "Service", "Missing");
seqPlus3++;
}
seqPrt3 = seq;
}
else { seqPrt3 = seq; }
break;
}
block = block.Remove(block.Length - 52);//<--- trim the sequence number and unwanted info
string[] Alladd;
List<string> sent = new List<string>();
if (!dupList.Contains(block)) //<--- if msg not found in duplicates validation list
{
//--------extract values--------------
if (block.Substring(0, 3) == "\r\nQ") //<--- if the msg. contains a priority code
{
Alladd = block.Substring(0, block.IndexOf(".")).Replace("\r\n", " ").Substring(4).Split(' ').Distinct().Where(x => !string.IsNullOrEmpty(x)).ToArray(); ;
}
else//<--- if no priority code
{
Alladd = block.Substring(0, block.IndexOf(".")).Replace("\r\n", " ").Substring(1).Split(' ').Distinct().Where(x => !string.IsNullOrEmpty(x)).ToArray(); ;
}
string From = block.Substring(block.IndexOf('.') + 1).Substring(0, 7);
string Msg = block.Substring(block.IndexOf('.') + 1);
Msg = Msg.Substring(Msg.IndexOf('\n') + 1);
//--------add msg content to the DB group table--------
using (TREEEntities TE1 = new TREEEntities())
{
TREE_group tg = new TREE_group()
{
GROUP_original = block,
GROUP_sent = Msg,
GROUP_dateTime = DateTime.Now,
GROUP_from = From,
GROUP_seq = seq,
GROUP_prt = PRT,
};
TE1.AddToTREE_group(tg);
TE1.SaveChanges();
GID = tg.GROUP_ID;
}
//--------validate addresses---------------
foreach (string TB in Alladd)
{
string email = "";
string typeB = "";
TREEEntities TE = new TREEEntities();
var q1 = from x in TE.TREE_users where x.USR_TypeB == TB && x.USR_flag == "act" select new { x.USR_email, x.USR_TypeB };
foreach (var itm in q1)
{
email = itm.USR_email;
typeB = itm.USR_TypeB;
}
//-------send mail if the user exist----
if (TB == typeB)
{
if (typeB == "BAHMVGF")
{
addToFtl(block);
}
try
{
sendMail SM = new sendMail();
SM.SendMail(Msg, "Message from: " + From, email);
//---save record in DB----
addToMsg(typeB, email,"sent","act",1,GID,seq);
sent.Add(typeB);
}
catch (Exception x)
{
addToMsg(typeB, email, "Failed", "act", 1, GID, seq);
addToLog(DateTime.Now, "Send message failed: " + x.Message, GID, "Service", "Warning");
}
}
//-------if no user exist----
else
{
if (TB == "BAHMVGF")
{
addToFtl(block);
}
addToMsg(TB, "No email", "Failed", "act", 1, GID, seq);
addToLog(DateTime.Now, "Send message failed, unknown Type-B address: " + TB, GID, "Service", "Warning");
}
}
if (sent.Count < Alladd.Count())//<--- if there is unsent addresses
{
StringBuilder b = new StringBuilder(block);
foreach (string add in sent)
{
b.Replace(add, "");//<--- remove address that has been sent from the original message and write new msg. to unsent folder
}
if (!Directory.Exists(MsgsPath + "\\Unsent"))
{
Directory.CreateDirectory(MsgsPath + "\\Unsent");
}
using (StreamWriter w = File.AppendText(MsgsPath + "\\Unsent\\" + e.Name))
{
w.WriteLine(b);
}
}
sent.Clear();
//---add to dupList to validate the next messages-------------
if (dupList.Count > DupCash)
{
dupList.RemoveAt(0);
}
dupList.Add(block);
//---move msg to archive folder-----------------
if (!Directory.Exists(MsgsPath + "\\Archive"))
{
Directory.CreateDirectory(MsgsPath + "\\Archive");
}
File.Move(MsgsPath + "\\" + e.Name, MsgsPath + "\\Archive\\" + e.Name);
}
else //<--- if message is a duplicate
{
addToLog(DateTime.Now, "Duplicated message, message not sent", seq, "Service", "Info");
//---move msg to duplicates folder-----------------
if (!Directory.Exists(MsgsPath + "\\Duplicates"))
{
Directory.CreateDirectory(MsgsPath + "\\Duplicates");
}
File.Move(MsgsPath + "\\" + e.Name, MsgsPath + "\\Duplicates\\" + e.Name);
}
}
catch (Exception x)
{
addToLog(DateTime.Now, "Error: " + x.Message, seq, "Service", "Alert");
if (!Directory.Exists(MsgsPath + "\\Unsent"))
{
Directory.CreateDirectory(MsgsPath + "\\Unsent");
}
//---move msg to Unsent folder-----------------
File.Move(MsgsPath + "\\" + e.Name, MsgsPath + "\\Unsent\\" + e.Name);
}
}
我想添加这个作为一个评论,但它超过了允许的字符数,所以这里开始 我在代码中注意到的第一件事是,您正在创建的事件处理程序中执行所有文件处理。这不是一个好的做法,您应该始终让您的FileSystemWatcher事件处理程序执行最少的工作,因为它可能会导致溢出,这可能是您所面临的问题。 相反,最好将工作委托给单独的线程。您可以将事件添加到队列中,让后台线程来处理它们。您可以过滤事件处理程序中的文件,这样队列就不会被垃圾填满 在事件处理程序中使用睡眠也被认为是一种不好的做法,因为这样会阻止FileSystemWatcher事件 允许的最大缓冲区大小为64K,除非您处理的是长路径,否则这不是建议的缓冲区大小。增加缓冲区的大小是昂贵的,因为它来自无法交换到磁盘的非分页内存,所以请尽可能保持缓冲区的小。要避免缓冲区溢出,请使用和属性过滤掉不需要的更改通知
最后,我建议在尝试编写代码之前,先阅读FileSystemWatcher并在线查看几个示例,因为Windows watcher有些脆弱,而且容易出错增加缓冲区大小会有帮助吗?我的所有文件都在本地专用服务器上,不在共享网络上。如果您需要帮助,并且认为这不是以前引用的问答的副本,您需要更具体一些,而不仅仅是它崩溃。我在事件查看器中看到了这一点:windows服务意外终止。您可以拆分为多个注释。@tbodt不必是个聪明人,答案是正确的。我建议您也阅读MSDN文章。