我正在使用此代码来监视某些文件夹中文件的创建:
_watcher = new RecoveringFileSystemWatcher(SourceFolder, "*.xml");
_watcher.Created += (_, e) =>
{
ProcessFile(e.Name);
};
RecoveringFileSystemWatcher是fileSystemWatcher的包装器。它的构造函数是:
public RecoveringFileSystemWatcher (string path, string filter)
{
_containedFSW = new FileSystemWatcher(path, filter);
}
该过程按预期工作,但是对于某些文件,随机地,抛出一个异常,表明该文件已被另一个进程使用。
这是在文件创建时启动的方法:
var nfo = new FileInfo(filePath);
if (nfo.Exists)
{
var archivoXml = nfo.Name;
string archivo = String.Empty;
try
{
string content = Task.Run(async () => await GetFileContent(filePath)).Result;
if (String.IsNullOrEmpty(content))
return false;
XmlDocument xml = new XmlDocument();
xml.LoadXml(content);
//The rest of the method
}
}
GetFileContent方法是这样的:
private async Task<string> GetFileContent(string filePath)
{
string content = String.Empty;
try
{
Console.Write("ONE - "); InfoLog.Save($"ONE {filePath}");
using (StreamReader sr = new StreamReader(filePath))
{
Console.Write("TWO - "); InfoLog.Save($"TWO {filePath}");
content = await sr.ReadToEndAsync().ConfigureAwait(false);
Console.Write($"THREE {(sr.BaseStream == null ? "Closed" : "Opened")} - "); InfoLog.Save($"THREE {(sr.BaseStream == null ? "Closed" : "Opened")} {filePath}");
sr.Close();
Console.WriteLine($"FOUR {(sr.BaseStream == null ? "Closed" : "Opened")}"); InfoLog.Save($"FOUR {(sr.BaseStream == null ? "Closed" : "Opened")} {filePath}");
}
}
catch (Exception ex)
{
InfoLog.Save($"XML file could be read -> {filePath}. See error log.");
ErrorLog.Save(ex);
}
return content;
}
查看我正在编写的用于调试过程的日志信息。
我遇到了一个案例,文件名为1112186.xml。...记录在日志中:
18/12/2018 19:12:10 ONE D:\GestorDocumental\Origen\1112186.xml
18/12/2018 19:12:10 XML file could not be read -> D:\GestorDocumental\Origen\1112186.xml. See error log.
如您所见,在“使用”指令处引发了异常。
如果我看到完整的日志,则可以看到以前从未使用过文件1112186.xml,因此,唯一的机会是FSW保持文件打开。我不知道为什么,但是看来这正在发生。
很明显,此过程正在锁定文件,因为当我退出控制台应用程序然后再次运行时,可以对文件进行处理。
对此有任何帮助吗?
谢谢 海梅
答案 0 :(得分:1)
我通常使用这种方法来检查文件是否被锁定。我是从stackoverflow中的link之一获得的。
public static bool IsFileClosed(string filepath)
{
bool fileClosed = false;
int retries = 20;
const int delay = 400; // set a delay period = retries*delay milliseconds
if (!File.Exists(filepath))
return false;
do
{
try
{
// Attempts to open then close the file in RW mode, denying other users to place any locks.
FileStream fs = File.Open(filepath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
fs.Close();
fileClosed = true; // success
}
catch (IOException) { }
retries--;
if (!fileClosed)
Thread.Sleep(delay);
}
while (!fileClosed && retries > 0);
return fileClosed;
}
这是一个名为FileTimerWatcher的新类(它将注入记录器):
public FileTimerWatcher(ILogger logger) : base(logger)
{
if (timer == null)
{
// Create a timer with a 1.5 second interval.
// monitor the files after 1.5 seconds.
timer = new Timer(delay);
// Hook up the event handler for the Elapsed event.
timer.Elapsed += new ElapsedEventHandler(ProcessFolder);
timer.AutoReset = true;
timer.Enabled = true;
}
}
private void ProcessFolder(object sender, ElapsedEventArgs e)
{
var LastChecked = DateTime.Now;
string[] files = System.IO.Directory.GetFiles(SourceDirectory, somefilter, System.IO.SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
ProcessFile(file); // process file here
}
}