2012-02-02 182 views
1

我有兩個服務。 1-客戶端2-服務器。兩項服務都通過套接字進行通信 客戶端包含文件系統觀察器。只要文件系統監視器檢測到指定文件夾中的新文件,就會建立到服務器的連接並將文件發送到服務器。 服務器偵聽特定端口並接受請求並接收文件並將詳細信息保存到數據庫。然後將成功/錯誤消息發送給客戶端。進程無法訪問文件,因爲它正在被另一個進程使用

第一次整個系統工作正常。但是,當文件系統監視器獲取第二個文件時,應用程序會生成異常「進程無法訪問該文件,並被另一進程使用」。再一次,當我調試服務時,沒有例外。無法獲得問題的確切原因。

任何幫助將不勝感激。

客戶端代碼:

namespace WindowsService1 
{ 
public partial class Client : ServiceBase 
{ 
    string hostIPAddress = string.Empty; 
    string processedFilePath = string.Empty; 
    int hostPort; 
    Socket socketClient; 
    IPEndPoint remoteEndPoint; 
    FileStream fs; 

    public PCMParserClient() 
    { 
     InitializeComponent(); 
    } 

    protected override void OnStart(string[] args) 
    { 
     hostIPAddress = ConfigurationManager.AppSettings["HostIP"]; 
     hostPort = int.Parse(ConfigurationManager.AppSettings["HostPort"]); 
     //File system watcher 
     FsWatcher.Path = ConfigurationManager.AppSettings["FileWatcherPath"]; 
     processedFilePath = ConfigurationManager.AppSettings["ProcessedFilePath"]; 
    } 

    protected override void OnStop() 
    { 
    } 

    private void FsWatcher_Created(object sender, System.IO.FileSystemEventArgs e) 
    { 
     try 
     { 
      socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);    
      IPAddress remoteIPAddress = IPAddress.Parse(hostIPAddress); 
      remoteEndPoint = new IPEndPoint(remoteIPAddress, hostPort); 
      //Establish the connection to server 
      socketClient.Connect(remoteEndPoint); 
      EventLog.WriteEntry(e.Name+"before"); 

       **//the below line generates teh exception for 2nd time onwards** 
       using (fs = new FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.Read)) 
       { 
        EventLog.WriteEntry("1"); 
        //Convert the file name in form of byte 
        byte[] fileNameByte = Encoding.ASCII.GetBytes(e.Name); 
        EventLog.WriteEntry(e.Name); 

        //4- to store the filename length(as int - 4bytes) 
        //8- to store the file content length(as long take 8 bytes) 
        int totalLength = 4 + fileNameByte.Length + 8; 

        //Clientdata[] reprents the data to sent to the server 
        //which represent the file details 
        byte[] clientData = new byte[totalLength]; 
        byte[] fileNameLength = BitConverter.GetBytes(fileNameByte.Length); 
        byte[] fileContentLength = BitConverter.GetBytes(fs.Length); 

        //Copy all the data ClientData array 
        fileNameLength.CopyTo(clientData, 0); 
        fileNameByte.CopyTo(clientData, 4); 
        fileContentLength.CopyTo(clientData, 4 + fileNameByte.Length); 

        //Send the data to server 
        socketClient.Send(clientData); 

        int byteRead = 0; 
        int bytesToRead = (int)fs.Length; 

        while (bytesToRead > 0) 
        { 
         byte[] data = new Byte[1500]; 
         byteRead = bytesToRead > 1500 ? 1500 : bytesToRead; 
         int n = fs.Read(data, 0, byteRead); 

         //Send the data to server 
         socketClient.Send(data); 
         bytesToRead -= n; 
        } 

        fs.Flush(); 
        //fs.Close(); 
        //fs.Dispose(); 
       } 


       //Code block to get the success/failure message from server 
       byte[] message = new byte[5]; 
       int msg = socketClient.Receive(message); 

       else if (Encoding.ASCII.GetString(message).Contains("Error")) 
       { 
        throw new Exception("Error occured while processing the file " + e.Name); 
       } 

     } 
     catch (SocketException ex) 
     { 
      ExceptionLogger.LogException(ex); 
     } 
     catch (IOException ex) 
     { 
      ExceptionLogger.LogException(ex); 
     } 
     catch (Exception ex) 
     { 
      ExceptionLogger.LogException(ex); 
     } 
     finally 
     { 
      if (socketClient != null && socketClient.Connected) 
      { 
       socketClient.Close(); 
      } 
     } 
    } 
} 

}

服務器代碼:

namespace PCMParserService 
{ 
public partial class ParserServer : ServiceBase 
{ 
    Socket serverSocket = null; 
    public Timer timer1; 
    IPEndPoint ipEndPoint; 

    public HL7ParserService() 
    { 
     InitializeComponent(); 
     timer1 = new Timer(1000); 
     timer1.Elapsed += new ElapsedEventHandler(timer1_Elapsed); 
    } 

    void timer1_Elapsed(object sender, ElapsedEventArgs e) 
    { 
     Socket handler = null; 
     try 
     { 
      // The program is suspended while waiting for an incoming connection. 
      // This is a synchronous TCP application 
      handler = serverSocket.Accept(); 

      byte[] fileDetails = new byte[1500]; 
      //Recieve the file details 
      handler.Receive(fileDetails); 
      int fileNameLength = BitConverter.ToInt32(fileDetails, 0); 
      string fileName = Encoding.ASCII.GetString(fileDetails, 4, fileNameLength); 
      EventLog.WriteEntry(fileNameLength.ToString(), System.Diagnostics.EventLogEntryType.Information); 
      int fileLength = BitConverter.ToInt32(fileDetails, 4 + fileNameLength); 

      filePath = ConfigurationManager.AppSettings["ProcessedDirectory"]; 

      FileStream fs = new FileStream(filePath + fileName, FileMode.Create, FileAccess.Write); 
      int byteRead = 0; 

      while (byteRead < fileLength) 
      { 
       byte[] data = new Byte[1500]; 
       //Recieve the data and write to the file 
       int r = handler.Receive(data); 
       fs.Write(data, 0, r); 
       byteRead += r; 
      } 
      fs.Flush(); 
      fs.Close(); 
      fs.Dispose(); 


      //-Code to Parse text file and save to db 
      FileStream fileStream = new FileStream(filePath + fileName, FileMode.Open, FileAccess.Read); 
      StreamReader sr = new StreamReader(fileStream); 
      ///Code 
      fileStream.Close(); 
      fileStream.Dispose(); 
      sr.Close(); 
      sbMessage.Append("</Message>"); 
      saveFileDetails(sbMessage.ToString()); 

      //-- End of File Parsing code 
      handler.Send(Encoding.ASCII.GetBytes("Done")); 
     } 
     catch (SocketException ex) 
     { 
      ExceptionLogger.LogException(ex, "Error occured while processing the file + " + filePath); 
      handler.Send(Encoding.ASCII.GetBytes("Error")); 
     } 
     catch (IOException ex) 
     { 
      ExceptionLogger.LogException(ex, "Error occured while processing the file + " + filePath); 
      handler.Send(Encoding.ASCII.GetBytes("Error")); 
     } 
     catch (SqlException ex) 
     { 
      ExceptionLogger.LogException(ex, "Error occured while processing the file + " + filePath); 
      handler.Send(Encoding.ASCII.GetBytes("Error")); 
     } 
     catch (Exception ex) 
     { 
      ExceptionLogger.LogException(ex, "Error occured while processing the file + " + filePath); 
      handler.Send(Encoding.ASCII.GetBytes("Error")); 
     } 
    } 

    protected override void OnStart(string[] args) 
    { 
     try 
     { 
      //The port on which the server listens 
      ipEndPoint = new IPEndPoint(IPAddress.Any, 8030); 

      //Defines the kind of socket we want :TCP 
      serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 

      //Bind the socket to the local end point(associate the socket to local end point) 
      serverSocket.Bind(ipEndPoint); 

      //listen for incoming connection attempt 
      // Start listening, only allow 100 connection to queue at the same time 
      serverSocket.Listen(100); 

      timer1.Start(); 
     } 
     catch (SocketException ex) 
     { 
      ExceptionLogger.LogException(ex, string.Empty); 
     } 
     catch (Exception ex) 
     { 
      ExceptionLogger.LogException(ex, string.Empty); 
     } 
    } 

    protected override void OnStop() 
    { 
     timer1.Stop(); 
    } 

    protected override void OnPause() 
    { 
     timer1.Stop(); 
    } 

    protected override void OnContinue() 
    { 
     timer1.Start(); 
    } 

    protected override void OnShutdown() 
    { 
     timer1.Stop(); 
    } 

} 
} 

回答

2

這通常是由過程寫作有沒有寫完的文件的文件引起的,並因此釋放該文件,當FileSystemWatcher通知您有觀看目錄中的新文件。

選項來緩解這種包括:

  • 具有通知後延遲處理該文件
  • 立即處理文件之前,但將其產生的任何文件「該進程無法訪問該文件它被另一個進程使用「放入隊列以便定期重試。

你通常不會看到調試/測試期間這個問題,因爲你會手動將文件複製到監控目錄或步進,通過您的代碼速度足夠慢,該文件已完成之前嘗試寫入打開它。

+0

沒有準確得到第二點。 – Madhusmita 2012-02-02 09:52:39

0

另外,要注意的另一件事是,你可以打開一個文件,指定多個對象對它有什麼類型的訪問(這可能會或可能不會影響你的情況)。

所以,與其寫:

FileStream fileStream = new FileStream(filePath + fileName, 
             FileMode.Open, 
             FileAccess.Read); 

你可以嘗試添加FileShare選項:

FileStream fileStream = new FileStream(filePath + filename, 
             FileMode.Open, 
             FileAccess.Read, 
             FileShare.Read)) 

通過指定一個合適的FileShare標誌,您可以訪問該文件,而無需等待它是關閉。例如,在上面的行中,FileShare.Read

允許隨後打開文件供閱讀。如果未指定此標誌,則在文件關閉之前,打開文件進行讀取(通過此進程或其他進程)的任何請求都將失敗。

相關問題