Windows服务中的异常 - 发生异常时服务停止

时间:2011-08-03 06:16:24

标签: visual-studio-2010 exception windows-services

我开发了一个Windows服务,可以监视新文件的文件夹。我的问题是,当发生异常时,服务停止工作。该服务的主要目的是: 1.观察文件夹以进行文件创建 2.读取文件 3.在数据库中插入文件的数据 我真正想做的是不要丢失任何文件插入!必须读取每个新文件并将其数据插入数据库中。 但是,如果发生异常,例如“进程无法访问文件'c:\ newfile.txt',因为它正被另一个进程使用。”,该进程将停止。我的服务代码是:

public partial class weatherService : ServiceBase
    {
        private FileSystemWatcher FSW;
        private FswHandler Handler;

        public weatherService()
        {
            InitializeComponent();            
        }

        protected override void OnStart(string[] args)
        {
            FSW = new FileSystemWatcher("c:\\cvvv", "*.txt");
            Handler = new FswHandler();

            FSW.Created += Handler.OnEvent;

            FSW.EnableRaisingEvents = true;    

        }

        protected override void OnStop()
        {
            FSW.EnableRaisingEvents = false;
            FSW.Dispose();
        }

        protected override void OnPause()
        {
            FSW.EnableRaisingEvents = false;
        }

        protected override void OnContinue()
        {
            FSW.EnableRaisingEvents = true;
        }
    }

处理程序代码是:

public class FswHandler
    {
        private string[] data;
        private StreamReader reader;
        private StreamWriter sw;

        public void OnEvent(Object source, FileSystemEventArgs Args)
        {
            LogEvent(" [reading file] ");
            readFile(Args.FullPath, Args.Name);
        }

        public void LogEvent(string msg) {
            sw = new StreamWriter("C:\\Users\\Olga\\Desktop\\weatherlog.txt", true);    
            sw.WriteLine("Action : "+ msg +" occured in " + DateTime.Now.ToString());
            sw.Close();
        }
        public void readFile(string path, string filename)
        {
            LogEvent(" [got in readFile] to read file " + filename);
            try
            {
                reader = new StreamReader(path);
            }
            catch (Exception ex)
            {
                LogEvent(ex.Message);
            }
            try
            {
                reader = File.OpenText(path);
            }
            catch (Exception ex)
            {
                LogEvent(ex.Message);
            }
            string titlesLine;
            string valuesLine;

            LogEvent(" [getting 1st line] ");

            titlesLine = reader.ReadLine();

            LogEvent(" [getting 2nd line] ");

            valuesLine = reader.ReadLine();

            LogEvent(" [splitting 2nd line] ");
            data = valuesLine.Split(new Char[] { ' ', '\t' });

            LogEvent(" [starting inserting] ");
            insData(filename);

            reader.Close();

        }

        public void insData(string filename) {
            string connString = "server=83.212.92.197;port=3306;database=mydata;uid=distusr;pwd=usdist1";
            MySqlConnection conn = new MySqlConnection(connString);
            MySqlCommand command = conn.CreateCommand();

            DateTime cdt = System.DateTime.Now;

            String.Format("{0:MM/dd/yyyy HH:mm:ss}", cdt);
            string dt = cdt.ToString();
            int space_pos = dt.IndexOf(" ");
            string date = dt.Substring(0, space_pos);
            string time = dt.Substring(space_pos+1, dt.Length-space_pos+1);

            command.CommandText = "INSERT INTO datainput(filename, measDate, measTime, out2, out3, out4, out5, out6, out7, out8, out9, out10," +
            "out11, out12, out13, out14, out15, out16, out17, out18, out19, out20," +
            "out21, out22, out23, out24, out25, out26, out27, out28, out29, out30," +
            "out31, out32, out33, out34, out35, out36, out37, out38, out39, out40," +
            "out41, out42, out43) VALUES ('" + filename + "','" + date + "','" + time +
            "','" + data[14] + "','" + data[15] + "','" + data[16] + "','" + data[17] + "'," +
            "'" + data[18] + "','" + data[19] + "','" + data[20] + "','" + data[21] + "','" + data[22] + 
            "','" + data[23] + "'," + "'" + data[24] + "','" + data[25] + "','" + data[26] + 
            "','" + data[27] + "','" + data[28] + "'," +"'" + data[29] + "','" + data[30] + 
            "','" + data[31] + "','" + data[32] + "','" + data[33] + "'," + "'" + data[34] + 
            "','" + data[35] + "','" + data[36] + "','" + data[37] + "','" + data[38] + "'," + 
            "'" + data[39] + "','" + data[40] + "','" + data[41] + "','" + data[42] + "','" + data[43] + 
            "'," + "'" + data[44] + "','" + data[45] + "','" + data[46] + "','" + data[47] + 
            "','" + data[48] + "'," + "'" + data[49] + "','" + data[50] + "','" + data[51] +
            "','" + data[52] + "','" + data[53] + "','" + data[54] + "','" + data[55] + "')";

            LogEvent(" [opening database] ");

            try{
                conn.Open();
            }
            catch (Exception ex){
                LogEvent(ex.Message);
            }

            LogEvent(" [executing query] ");

            try
            {
                command.ExecuteNonQuery();
            }
            catch (Exception ex){
                LogEvent(ex.Message);
            }

            LogEvent(" [data have been inserted] ");


            conn.Close();
        }
    }

我可以做些什么来避免丢失文件?我也试过

        protected void DelayExecution(int nSeconds)
        {
            DateTime end = DateTime.UtcNow.AddSeconds (nSeconds);
            while (DateTime.UtcNow < end){}
        }

        try
        {
            reader = File.OpenText(path);
        }
        catch (Exception ex)
        {
            LogEvent(ex.Message);
            DelayExecution(2);
            readFile(path, filename);
        }

但问题仍然存在。在这种情况下,它从函数开始并在进程在db中插入数据之后再进入[获取第1行]。我使用LogEvent,所以我可以调试我的服务,这就是我有很多LogEvents执行的原因。

任何帮助都会很棒......

1 个答案:

答案 0 :(得分:0)

您可以尝试在具有Thread.Sleep的循环中使用此扩展方法:

/// <summary>
/// Extension methods for FileInfo
/// </summary>
public static class ExtensionMethods_FileInfo
{
    /// <summary>
    /// Verifies if the file is in use
    /// </summary>
    /// <param name="fi">Original FileInfo object</param>
    /// <returns>Returns a boolean value with the state of the file</returns>
    public static Boolean IsInUse(this FileInfo fi)
    {
        try
        {
            if (File.Exists(fi.FullName))
                File.Move(fi.FullName, fi.FullName);
            return false;
        }
        catch (IOException)
        {
            return true;
        }
    }
}

我建议您不要在“catch”部分编写代码(除了日志记录),因为它可能会导致更多错误。

while (new FileInfo(path).IsInUse())
    System.Threading.Thread.Sleep(1000);

// Then do your job...