我的代码是
var files = Directory.GetFiles(this.DirectoryPath, this.File.FileMatchPattern, SearchOption.TopDirectoryOnly);
其中File.FileMatchPattern看起来像“FileName * .csv”,而DirectoryPath是unc共享。
在dev中,这段代码执行得很好,但是我们得到了以下异常:
ERROR 8 Guggenheim.Pipeline.Services.FileWatcher.WatchedFile - CheckForFile
System.IO.IOException: The process cannot access the file '\\il1tstbrsapp01\prodapps\FileWatcher\EPAMFileWatcherDropFolderTest\20140531_0171' because it is being used by another process.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileSystemEnumerableIterator`1.CommonInit()
at System.IO.FileSystemEnumerableIterator`1..ctor(String path, String originalUserPath, String searchPattern, SearchOption searchOption, SearchResultHandler`1 resultHandler, Boolean checkHost)
at System.IO.Directory.GetFiles(String path, String searchPattern, SearchOption searchOption)
at Guggenheim.Pipeline.Services.FileWatcher.WatchedFile.CheckForFile() in e:\VS\FixedIncome\Pipeline.Services\Guggenheim.Pipeline.Services.FileWatcher\Guggenheim.Pipeline.Services.FileWatcher\WatchedFile.cs:line 71
奇怪的是错误的路径是目录而不是文件,应该注意FileSystemWatcher正在监视该目录。
我真的不在乎该文件是否被另一个进程访问,我只是想知道它是否存在于此处。有没有办法在目录中搜索.NET / C#中的文件而不关心锁?
编辑: 我正在使用以下代码观看该文件夹:
Watcher = new FileSystemWatcher(group.WatchDirectory);
Watcher.IncludeSubdirectories = true;
Watcher.NotifyFilter = NotifyFilters.DirectoryName;
Watcher.Created += Watcher_Created;
WatchedGroups = new List<WatchedGroup>();
Watcher.EnableRaisingEvents = true;
然后在创建的文件夹上:
private void Watcher_Created(object sender, FileSystemEventArgs e)
{
WatchedGroup group = new WatchedGroup(Group, e.FullPath);
if (group.IsGroupReady)
group_GroupReady(group, new EventArgs());
else
{
group.GroupFailed += group_GroupFailed;
group.GroupReady += group_GroupReady;
WatchedGroups.Add(group);
}
}
WatchedGroup如下:
public class WatchedGroup : IDisposable
{
public FileWatcherGroup Group { get; private set; }
private Timer GroupTimer { get; set; }
public List<WatchedFile> Files { get; private set; }
public string DirectoryPath { get; private set; }
public event EventHandler GroupReady;
public event EventHandler GroupFailed;
public bool IsGroupReady { get; private set; }
private readonly object sync = new object();
public WatchedGroup(FileWatcherGroup group, string directory)
{
this.Group = group;
this.GroupTimer = new Timer(Group.WaitTimeInMinutes * 60000);
this.GroupTimer.Elapsed += GroupTimer_Elapsed;
this.DirectoryPath = directory;
Files = Group.Files.Select(f => new WatchedFile(f, directory)).ToList();
CheckGroupReady();
if (IsGroupReady)
return;
foreach(var file in Files)
{
file.FileAvailable += File_FileAvailable;
}
this.GroupTimer.Start();
}
private void StopFiles()
{
foreach(var file in Files)
{
file.Stop();
}
this.GroupTimer.Stop();
}
private void CheckFiles()
{
foreach(var file in Files.Where(f => !f.IsFileAvailable))
{
file.CheckForFile();
}
}
private void CheckGroupReady()
{
lock (sync)
{
if (!IsGroupReady && Files.All(f => f.IsFileAvailable))
{
IsGroupReady = true;
StopFiles();
if (GroupReady != null)
GroupReady(this, new EventArgs());
}
}
}
private void File_FileAvailable(object sender, EventArgs e)
{
CheckGroupReady();
}
private void GroupTimer_Elapsed(object sender, ElapsedEventArgs e)
{
GroupTimer.Stop();
StopFiles();
CheckFiles();
CheckGroupReady();
if (!IsGroupReady && GroupFailed != null)
GroupFailed(this, new EventArgs());
}
public void Dispose()
{
this.StopFiles();
this.Files.Clear();
}
}
WatchedFile如下:
public class WatchedFile
{
private static readonly ILog logger = LogManager.GetLogger(typeof(WatchedFile));
public WatcherFile File { get; private set; }
public bool IsFileAvailable { get; private set; }
public event EventHandler FileAvailable;
private FileSystemWatcher Watcher { get; set; }
public string DirectoryPath { get; private set; }
public string FilePath { get; private set; }
public WatchedFile(WatcherFile file, string directoryPath)
{
this.File = file;
this.DirectoryPath = directoryPath;
CheckForFile();
if (IsFileAvailable)
return;
try
{
Watcher = new FileSystemWatcher(directoryPath);
Watcher.Filter = File.FileMatchPattern;
Watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.DirectoryName;
Watcher.Created += Watcher_Created;
Watcher.EnableRaisingEvents = true;
}
catch(Exception ex)
{
logger.Error("WatchedFile FileSystemWatcher", ex);
throw;
}
}
public void Stop()
{
if(Watcher != null)
Watcher.EnableRaisingEvents = false;
}
private void Watcher_Created(object sender, FileSystemEventArgs e)
{
this.FilePath = e.FullPath;
MarkFileAvailable();
}
private readonly object sync = new object();
private void MarkFileAvailable()
{
lock(sync)
{
if(!this.IsFileAvailable)
{
this.IsFileAvailable = true;
if (FileAvailable != null)
FileAvailable(this, new EventArgs());
}
}
}
public bool CheckForFile()
{
try
{
var files = Directory.GetFiles(this.DirectoryPath, this.File.FileMatchPattern, SearchOption.TopDirectoryOnly);
if (files.Length > 0)
{
this.FilePath = files.First();
MarkFileAvailable();
}
return this.IsFileAvailable;
}
catch(Exception ex)
{
logger.Error("CheckForFile", ex);
throw;
}
}
}
此代码的目的是允许最终用户删除网络共享上的文件夹,该文件应该包含由模式定义的一组文件(FileName * .csv作为示例)以及所有文件它会在一定时间内出现,触发下游系统拾取的事件,如果不是,则会触发故障事件。