C# 缺少具有后台线程的FileSystemWatcher来移动文件
我有一个将文件从源文件夹移动到目标文件夹的简单要求。这些文件的大小约为5mb,每次到达3个(每5秒) 我现在使用的机制似乎是移动文件,但是如果目标文件夹在几秒钟内无法访问,则要从源目录处理的文件不会排队,而是会丢失 我的问题是如何创建一个包含在源目录中创建的所有文件的队列,并将这些文件移动到目标?我需要使用后台线程吗 我的观察者代码如下所示C# 缺少具有后台线程的FileSystemWatcher来移动文件,c#,multithreading,queue,backgroundworker,filesystemwatcher,C#,Multithreading,Queue,Backgroundworker,Filesystemwatcher,我有一个将文件从源文件夹移动到目标文件夹的简单要求。这些文件的大小约为5mb,每次到达3个(每5秒) 我现在使用的机制似乎是移动文件,但是如果目标文件夹在几秒钟内无法访问,则要从源目录处理的文件不会排队,而是会丢失 我的问题是如何创建一个包含在源目录中创建的所有文件的队列,并将这些文件移动到目标?我需要使用后台线程吗 我的观察者代码如下所示 public sealed class Watcher { int eventCount = 0; #region
public sealed class Watcher
{
int eventCount = 0;
#region Private Members
/// <summary>
/// File system watcher variable.
/// </summary>
private FileSystemWatcher fsw = null;
/// <summary>
/// Destination path to use.
/// </summary>
private string destination = @"c:\temp\doc2\";
/// <summary>
/// Source path to monitor.
/// </summary>
private string source = @"c:\temp\doc\";
/// <summary>
/// Default filter type is all files.
/// </summary>
private string filter = "*.bmp";
/// <summary>
/// Monitor all sub directories in the source folder.
/// </summary>
private bool includeSubdirectories = true;
/// <summary>
/// Background worker which will Move files.
/// </summary>
private BackgroundWorker bgWorker = null;
/// <summary>
/// Toggle flag to enable copying files and vice versa.
/// </summary>
private bool enableCopyingFiles = false;
/// <summary>
/// File System watcher lock.
/// </summary>
private object fswLock = new object();
private static Watcher watcherInstance;
#endregion
#region Public Properties
public static Watcher WatcherInstance
{
get
{
if (watcherInstance == null)
{
watcherInstance = new Watcher();
}
return watcherInstance;
}
}
public string Source
{
get
{
return source;
}
set
{
source = value;
}
}
public string Destination
{
get
{
return destination;
}
set
{
destination = value;
}
}
public string Filter
{
get
{
return filter;
}
set
{
filter = value;
}
}
public bool MonitorSubDirectories
{
get
{
return includeSubdirectories;
}
set
{
includeSubdirectories = value;
}
}
public bool EnableCopyingFiles
{
get
{
return enableCopyingFiles;
}
set
{
enableCopyingFiles = value;
}
}
public FileSystemWatcher FSW
{
get
{
return fsw;
}
set
{
fsw = value;
}
}
#endregion
#region Construction
/// <summary>
/// Constructor.
/// </summary>
public Watcher()
{
// Intentionally left blank.
}
#endregion
#region Public Methods
/// <summary>
/// Method which will initialise the required
/// file system watcher objects to starting watching.
/// </summary>
public void InitialiseFSW()
{
fsw = new FileSystemWatcher();
bgWorker = new BackgroundWorker();
}
/// <summary>
/// Method which will start watching.
/// </summary>
public void StartWatch()
{
if (fsw != null)
{
fsw.Path = source;
fsw.Filter = filter;
fsw.IncludeSubdirectories = includeSubdirectories;
fsw.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.LastAccess;
// Setup events.
fsw.Created += fsw_Created;
// Important to set the below otherwise no events will be raised.
fsw.EnableRaisingEvents = enableCopyingFiles;
bgWorker.DoWork += bgWorker_DoWork;
}
else
{
Trace.WriteLine("File System Watcher is not initialised. Setting ISS Fault Alarm Bit");
//CommonActions.SetAlarmBit(ApplicationConstants.tag_AlarmTag, ApplicationConstants.bit_ISSFault);
}
}
/// <summary>
/// Method to stop watch.
/// </summary>
public void StopWatch()
{
// Stop Watcher.
if (bgWorker != null)
{
bgWorker.DoWork -= bgWorker_DoWork;
}
if (fsw != null)
{
fsw.Created -= fsw_Created;
}
}
#endregion
#region Private Methods
/// <summary>
/// Method which will do the work on the background thread.
/// Currently Move files from source to destination and
/// monitor disk capacity.
/// </summary>
/// <param name="sender">Object Sender</param>
/// <param name="e">Event Arguments</param>
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
Trace.WriteLine("ZZZZZ..Event Count:" + eventCount.ToString());
// Extract the file names form the arguments.
FileSystemEventArgs fsea = (FileSystemEventArgs)e.Argument;
// Form the correct filename.
// An assumption has been made that there will always be an '&' symbol in the filename.
// An assumption has been made that the batch code will be added before the first '&' symbol.
string newFileName = string.Empty;
//// First character we are looking for has been found.
//// Sanity checks.
//if (CommonActions.ExtDictionary != null)
//{
// // Add the batch Code.
// // newFileName = fnParts[i] + "_" + CommonActions.ExtDictionary["BatchID"] + "_" + "&";
// // Add the batch code before the filename for easy sorting in windows explorer.
// newFileName = CommonActions.ExtDictionary["BatchID"] + "_" + fsea.Name;
//}
//else
//{
// Batch Code not found. So prefix with hardcoded text.
newFileName = "BatchCode" + "_" + fsea.Name;
//newFileName = fsea.Name;
//}
// We should now have the fully formed filename now.
// Move the file to the new location
string destPath = destination + @"\" + newFileName;
var fi = new FileInfo(fsea.FullPath);
// TODO Check if the file exist.
if (File.Exists(Path.Combine(Source, fsea.Name)))
{
// Check if the file is accessiable.
if (IsAccessible(fi, FileMode.Open, FileAccess.Read))
{
if (!File.Exists(destPath))
{
try
{
// Copy the file.
//File.Copy(fsea.FullPath, destPath);
// Move the file.
//File.Move(fsea.FullPath, destPath);
File.Copy(fsea.FullPath, destPath);
File.SetAttributes(destPath, FileAttributes.ReadOnly);
//Stopwatch sWatch = Stopwatch.StartNew();
//TimeSpan fileDropTimeout = new TimeSpan(0, 0, 10);
//bool fileActionSuccess = false;
//do
//{
// // Copy the file.
// //File.Copy(fsea.FullPath, destPath);
// // Move the file.
// //File.Move(fsea.FullPath, destPath);
// File.Copy(fsea.FullPath, destPath);
// File.SetAttributes(destPath, FileAttributes.ReadOnly);
// fileActionSuccess = true;
//} while (sWatch.Elapsed < fileDropTimeout);
//if(!fileActionSuccess)
//{
// Trace.WriteLine("File Move or File Attribute settings failed.");
// throw new Exception();
//}
// Wait before checking for the file exists at destination.
Thread.Sleep(Convert.ToInt32(ConfigurationManager.AppSettings["ExistsAtDestination"]));
// Check if the file has actually been moved to dest.
if (!File.Exists(destPath))
{
// TODO Raise alarms here.
Trace.WriteLine("Failed to Move. File does not exist in destination. Setting ISS Fault Alarm bit");
//CommonActions.SetAlarmBit(ApplicationConstants.tag_AlarmTag, ApplicationConstants.bit_ISSFault);
// Notify HMI about the error type.
Trace.WriteLine("Failed to Move. File does not exist in destination. Setting ISS File Move Fault Alarm bit");
}
}
catch (Exception ex)
{
// TODO log the exception and Raise alarm?
Trace.WriteLine("Failed to Move or set attributes on file. Setting ISS Fault Alarm bit");
//CommonActions.SetAlarmBit(ApplicationConstants.tag_AlarmTag, ApplicationConstants.bit_ISSFault);
// Notify HMI about the error type.
Trace.WriteLine("Failed to Move or set attributes on file. Setting ISS File Move Fault Alarm bit");
}
}
else
{
Trace.WriteLine("File Move failed as the file: " + newFileName + " already exists in the destination folder");
}
}
else
{
Trace.WriteLine("File Move failed. File is not accessible");
}
}
}
/// <summary>
/// Event which is raised when a file is created in the folder which is being watched.
/// </summary>
/// <param name="sender">Object sender</param>
/// <param name="e">Event arguments</param>
private void fsw_Created(object sender, FileSystemEventArgs e)
{
lock (fswLock)
{
eventCount++;
// Start the background worker.
// Check whether if the background worker is busy if not continue.
if (!bgWorker.IsBusy)
{
bgWorker.RunWorkerAsync(e);
}
else
{
Trace.WriteLine("An attempt to use background worker for concurrent tasks has been encountered ");
// Worker thread is busy.
int busyCount = 0;
while (busyCount < 4)
{
// Wait for 500ms and try again.
Thread.Sleep(500);
if (!bgWorker.IsBusy)
{
bgWorker.RunWorkerAsync(e);
break;
}
else
{
Trace.WriteLine("An attempt to use background worker for concurrent tasks has been encountered, attempt " + busyCount);
busyCount++;
}
}
}
}
}
/// <summary>
/// Extension method to check if a file is accessible.
/// </summary>
/// <param name="fi">File Info</param>
/// <param name="mode">File Mode</param>
/// <param name="access">File Access</param>
/// <returns>Attempts three times. True if the file is accessible</returns>
private bool IsAccessible(FileInfo fi, FileMode mode, FileAccess access)
{
bool hasAccess = false;
int i = 0;
while (!hasAccess)
{
try
{
using (var fileStream = File.Open(fi.FullName, mode, access))
{
}
hasAccess = true;
i = 1;
break;
}
catch (Exception ex)
{
if (i < 4)
{
// We will swallow the exception, wait and try again.
Thread.Sleep(500);
// Explicitly set hasaccess flag.
hasAccess = false;
i++;
}
else
{
i = 0;
Trace.WriteLine("Failed to Move. File is not accessable. " + ex.ToString());
// Notify HMI
Trace.WriteLine("Failed to Move. File is not accessable.. Setting ISS Fault Alarm bit");
//CommonActions.SetAlarmBit(ApplicationConstants.tag_AlarmTag, ApplicationConstants.bit_ISSFault);
// Notify HMI about the error type.
Trace.WriteLine("Failed to Move. File is not accessable.. Setting ISS File Move Fault Alarm bit");
//CommonActions.SetAlarmBit(ApplicationConstants.tag_AlarmTag, ApplicationConstants.bit_ISSFileCopyFault);
// Explicitly set hasaccess flag.
hasAccess = false;
break;
}
}
}
// return hasAccess;
return true;
}
#endregion
}
这些是我的发现,最终似乎可以移动文件而不丢失任何文件 后台工作人员不是正确的使用对象 为每个文件创建一个任务,让它完成自己的任务 更新后的watcher类如下所示
public sealed class Watcher
{
int eventCount = 0;
#region Private Members
/// <summary>
/// File system watcher variable.
/// </summary>
private FileSystemWatcher fsw = null;
/// <summary>
/// Destination path to use.
/// </summary>
private string destination = @"c:\temp\doc2\";
/// <summary>
/// Source path to monitor.
/// </summary>
private string source = @"c:\temp\doc\";
/// <summary>
/// Default filter type is all files.
/// </summary>
private string filter = "*.bmp";
/// <summary>
/// Monitor all sub directories in the source folder.
/// </summary>
private bool includeSubdirectories = true;
/// <summary>
/// Background worker which will Move files.
/// </summary>
private BackgroundWorker bgWorker = null;
/// <summary>
/// Toggle flag to enable copying files and vice versa.
/// </summary>
private bool enableCopyingFiles = false;
/// <summary>
/// File System watcher lock.
/// </summary>
private object fswLock = new object();
private static Watcher watcherInstance;
#endregion
#region Public Properties
public static Watcher WatcherInstance
{
get
{
if (watcherInstance == null)
{
watcherInstance = new Watcher();
}
return watcherInstance;
}
}
public string Source
{
get
{
return source;
}
set
{
source = value;
}
}
public string Destination
{
get
{
return destination;
}
set
{
destination = value;
}
}
public string Filter
{
get
{
return filter;
}
set
{
filter = value;
}
}
public bool MonitorSubDirectories
{
get
{
return includeSubdirectories;
}
set
{
includeSubdirectories = value;
}
}
public bool EnableCopyingFiles
{
get
{
return enableCopyingFiles;
}
set
{
enableCopyingFiles = value;
}
}
public FileSystemWatcher FSW
{
get
{
return fsw;
}
set
{
fsw = value;
}
}
#endregion
#region Construction
/// <summary>
/// Constructor.
/// </summary>
public Watcher()
{
// Intentionally left blank.
}
#endregion
#region Public Methods
/// <summary>
/// Method which will initialise the required
/// file system watcher objects to starting watching.
/// </summary>
public void InitialiseFSW()
{
fsw = new FileSystemWatcher();
bgWorker = new BackgroundWorker();
}
/// <summary>
/// Method which will start watching.
/// </summary>
public void StartWatch()
{
if (fsw != null)
{
fsw.Path = source;
fsw.Filter = filter;
fsw.IncludeSubdirectories = includeSubdirectories;
fsw.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.LastAccess;
// Setup events.
fsw.Created += fsw_Created;
// Important to set the below otherwise no events will be raised.
fsw.EnableRaisingEvents = enableCopyingFiles;
bgWorker.DoWork += bgWorker_DoWork;
}
else
{
Trace.WriteLine("File System Watcher is not initialised. Setting ISS Fault Alarm Bit");
//CommonActions.SetAlarmBit(ApplicationConstants.tag_AlarmTag, ApplicationConstants.bit_ISSFault);
}
}
/// <summary>
/// Method to stop watch.
/// </summary>
public void StopWatch()
{
// Stop Watcher.
if (bgWorker != null)
{
bgWorker.DoWork -= bgWorker_DoWork;
}
if (fsw != null)
{
fsw.Created -= fsw_Created;
}
}
#endregion
#region Private Methods
/// <summary>
/// Method which will do the work on the background thread.
/// Currently Move files from source to destination and
/// monitor disk capacity.
/// </summary>
/// <param name="sender">Object Sender</param>
/// <param name="e">Event Arguments</param>
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
}
private void PerformFileActions(string sourcePath)
{
string extractedFileName = Path.GetFileName(sourcePath);
string newFileName = string.Empty;
newFileName = "BatchCode" + "_" + extractedFileName;
// We should now have the fully formed filename now.
// Move the file to the new location
string destPath = destination + @"\" + newFileName;
var fi = new FileInfo(sourcePath);
// TODO Check if the file exist.
if (File.Exists(Path.Combine(Source, extractedFileName)))
{
// Check if the file is accessiable.
if (IsAccessible(fi, FileMode.Open, FileAccess.Read))
{
if (!File.Exists(destPath))
{
try
{
File.Copy(sourcePath, destPath);
File.SetAttributes(destPath, FileAttributes.ReadOnly);
// Wait before checking for the file exists at destination.
Thread.Sleep(Convert.ToInt32(ConfigurationManager.AppSettings["ExistsAtDestination"]));
// Check if the file has actually been moved to dest.
if (!File.Exists(destPath))
{
// TODO Raise alarms here.
Trace.WriteLine("Failed to Move. File does not exist in destination. Setting ISS Fault Alarm bit");
//CommonActions.SetAlarmBit(ApplicationConstants.tag_AlarmTag, ApplicationConstants.bit_ISSFault);
// Notify HMI about the error type.
Trace.WriteLine("Failed to Move. File does not exist in destination. Setting ISS File Move Fault Alarm bit");
}
}
catch (Exception ex)
{
// TODO log the exception and Raise alarm?
Trace.WriteLine("Failed to Move or set attributes on file. Setting ISS Fault Alarm bit");
//CommonActions.SetAlarmBit(ApplicationConstants.tag_AlarmTag, ApplicationConstants.bit_ISSFault);
// Notify HMI about the error type.
Trace.WriteLine("Failed to Move or set attributes on file. Setting ISS File Move Fault Alarm bit");
}
}
else
{
Trace.WriteLine("File Move failed as the file: " + newFileName + " already exists in the destination folder");
}
}
else
{
Trace.WriteLine("File Move failed. File is not accessible");
}
}
}
/// <summary>
/// Event which is raised when a file is created in the folder which is being watched.
/// </summary>
/// <param name="sender">Object sender</param>
/// <param name="e">Event arguments</param>
private void fsw_Created(object sender, FileSystemEventArgs e)
{
lock (fswLock)
{
DateTime lastRead = DateTime.MinValue;
DateTime lastWriteTime = File.GetCreationTime(e.FullPath);
if (lastWriteTime != lastRead)
{
eventCount++;
// Start a new task and forget.
Task.Factory.StartNew(() => {
PerformFileActions(e.FullPath);
});
lastRead = lastWriteTime;
}
}
}
/// <summary>
/// Extension method to check if a file is accessible.
/// </summary>
/// <param name="fi">File Info</param>
/// <param name="mode">File Mode</param>
/// <param name="access">File Access</param>
/// <returns>Attempts three times. True if the file is accessible</returns>
private bool IsAccessible(FileInfo fi, FileMode mode, FileAccess access)
{
bool hasAccess = false;
int i = 0;
while (!hasAccess)
{
try
{
using (var fileStream = File.Open(fi.FullName, mode, access))
{
}
hasAccess = true;
i = 1;
break;
}
catch (Exception ex)
{
if (i < 4)
{
// We will swallow the exception, wait and try again.
Thread.Sleep(500);
// Explicitly set hasaccess flag.
hasAccess = false;
i++;
}
else
{
i = 0;
Trace.WriteLine("Failed to Move. File is not accessable. " + ex.ToString());
// Notify HMI
Trace.WriteLine("Failed to Move. File is not accessable.. Setting ISS Fault Alarm bit");
//CommonActions.SetAlarmBit(ApplicationConstants.tag_AlarmTag, ApplicationConstants.bit_ISSFault);
// Notify HMI about the error type.
Trace.WriteLine("Failed to Move. File is not accessable.. Setting ISS File Move Fault Alarm bit");
//CommonActions.SetAlarmBit(ApplicationConstants.tag_AlarmTag, ApplicationConstants.bit_ISSFileCopyFault);
// Explicitly set hasaccess flag.
hasAccess = false;
break;
}
}
}
// return hasAccess;
return true;
}
#endregion
}
公共密封类监视程序
{
int eventCount=0;
#区域私人成员
///
///文件系统监视程序变量。
///
私有文件系统监视程序fsw=null;
///
///要使用的目标路径。
///
私有字符串目标=@“c:\temp\doc2\”;
///
///要监视的源路径。
///
私有字符串源=@“c:\temp\doc\”;
///
///默认过滤器类型为“所有文件”。
///
私有字符串筛选器=“*.bmp”;
///
///监视源文件夹中的所有子目录。
///
私有bool includeSubdirectories=true;
///
///将移动文件的后台工作程序。
///
私有BackgroundWorker bgWorker=null;
///
///切换标志以启用复制文件,反之亦然。
///
private bool enableCopyingFiles=false;
///
///文件系统监视程序锁。
///
私有对象fswLock=新对象();
私人静态观察者观察站;
#端区
#区域公共财产
公共静态观察程序
{
收到
{
if(watcherInstance==null)
{
watcherInstance=新的观察者();
}
返回观察站;
}
}
公共字符串源
{
收到
{
返回源;
}
设置
{
来源=价值;
}
}
公共字符串目的地
{
收到
{
返回目的地;
}
设置
{
目的地=价值;
}
}
公共字符串过滤器
{
收到
{
回流过滤器;
}
设置
{
过滤器=值;
}
}
公共布尔监视器子目录
{
收到
{
返回includeSubdirectories;
}
设置
{
includeSubdirectories=值;
}
}
公共bool启用copyingfiles
{
收到
{
返回enableCopyingFiles;
}
设置
{
enableCopyingFiles=值;
}
}
公共文件系统监视程序FSW
{
收到
{
返回fsw;
}
设置
{
fsw=值;
}
}
#端区
#区域建设
///
///构造器。
///
公众观察者()
{
//故意留下空白。
}
#端区
#区域公共方法
///
///方法,该方法将初始化所需的
///文件系统监视程序对象以开始监视。
///
public void InitialiseFSW()
{
fsw=newfilesystemwatcher();
bgWorker=新的BackgroundWorker();
}
///
///方法,该方法将开始监视。
///
公共无效StartWatch()
{
如果(fsw!=null)
{
路径=源;
fsw.Filter=过滤器;
fsw.IncludeSubdirectories=IncludeSubdirectories;
fsw.NotifyFilter=NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.LastAccess;
//设置事件。
fsw.Created+=fsw_Created;
//请务必设置以下选项,否则不会引发任何事件。
fsw.EnableRaisingEvents=启用复制文件;
bgWorker.DoWork+=bgWorker\u DoWork;
}
其他的
{
Trace.WriteLine(“文件系统监视程序未初始化。设置ISS故障报警位”);
//CommonActions.SetAlarmBit(ApplicationConstants.tag\u AlarmTag,ApplicationConstants.bit\u ISSFault);
}
}
///
///方法停止监视。
///
公众免费秒表()
{
//停止观察者。
if(bgWorker!=null)
{
bgWorker.DoWork-=bgWorker\u DoWork;
}
如果(fsw!=null)
{
fsw.Created-=fsw_Created;
}
}
#端区
#区域私有方法
///
///方法,该方法将在后台线程上执行工作。
///当前将文件从源移动到目标和
///监视磁盘容量。
///
///对象发送器
///事件参数
私有void bgWorker\u DoWork(对象发送方,DoWorkEventArgs e)
{
}
私人无效行为文件(strin)
public sealed class Watcher
{
int eventCount = 0;
#region Private Members
/// <summary>
/// File system watcher variable.
/// </summary>
private FileSystemWatcher fsw = null;
/// <summary>
/// Destination path to use.
/// </summary>
private string destination = @"c:\temp\doc2\";
/// <summary>
/// Source path to monitor.
/// </summary>
private string source = @"c:\temp\doc\";
/// <summary>
/// Default filter type is all files.
/// </summary>
private string filter = "*.bmp";
/// <summary>
/// Monitor all sub directories in the source folder.
/// </summary>
private bool includeSubdirectories = true;
/// <summary>
/// Background worker which will Move files.
/// </summary>
private BackgroundWorker bgWorker = null;
/// <summary>
/// Toggle flag to enable copying files and vice versa.
/// </summary>
private bool enableCopyingFiles = false;
/// <summary>
/// File System watcher lock.
/// </summary>
private object fswLock = new object();
private static Watcher watcherInstance;
#endregion
#region Public Properties
public static Watcher WatcherInstance
{
get
{
if (watcherInstance == null)
{
watcherInstance = new Watcher();
}
return watcherInstance;
}
}
public string Source
{
get
{
return source;
}
set
{
source = value;
}
}
public string Destination
{
get
{
return destination;
}
set
{
destination = value;
}
}
public string Filter
{
get
{
return filter;
}
set
{
filter = value;
}
}
public bool MonitorSubDirectories
{
get
{
return includeSubdirectories;
}
set
{
includeSubdirectories = value;
}
}
public bool EnableCopyingFiles
{
get
{
return enableCopyingFiles;
}
set
{
enableCopyingFiles = value;
}
}
public FileSystemWatcher FSW
{
get
{
return fsw;
}
set
{
fsw = value;
}
}
#endregion
#region Construction
/// <summary>
/// Constructor.
/// </summary>
public Watcher()
{
// Intentionally left blank.
}
#endregion
#region Public Methods
/// <summary>
/// Method which will initialise the required
/// file system watcher objects to starting watching.
/// </summary>
public void InitialiseFSW()
{
fsw = new FileSystemWatcher();
bgWorker = new BackgroundWorker();
}
/// <summary>
/// Method which will start watching.
/// </summary>
public void StartWatch()
{
if (fsw != null)
{
fsw.Path = source;
fsw.Filter = filter;
fsw.IncludeSubdirectories = includeSubdirectories;
fsw.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.LastAccess;
// Setup events.
fsw.Created += fsw_Created;
// Important to set the below otherwise no events will be raised.
fsw.EnableRaisingEvents = enableCopyingFiles;
bgWorker.DoWork += bgWorker_DoWork;
}
else
{
Trace.WriteLine("File System Watcher is not initialised. Setting ISS Fault Alarm Bit");
//CommonActions.SetAlarmBit(ApplicationConstants.tag_AlarmTag, ApplicationConstants.bit_ISSFault);
}
}
/// <summary>
/// Method to stop watch.
/// </summary>
public void StopWatch()
{
// Stop Watcher.
if (bgWorker != null)
{
bgWorker.DoWork -= bgWorker_DoWork;
}
if (fsw != null)
{
fsw.Created -= fsw_Created;
}
}
#endregion
#region Private Methods
/// <summary>
/// Method which will do the work on the background thread.
/// Currently Move files from source to destination and
/// monitor disk capacity.
/// </summary>
/// <param name="sender">Object Sender</param>
/// <param name="e">Event Arguments</param>
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
}
private void PerformFileActions(string sourcePath)
{
string extractedFileName = Path.GetFileName(sourcePath);
string newFileName = string.Empty;
newFileName = "BatchCode" + "_" + extractedFileName;
// We should now have the fully formed filename now.
// Move the file to the new location
string destPath = destination + @"\" + newFileName;
var fi = new FileInfo(sourcePath);
// TODO Check if the file exist.
if (File.Exists(Path.Combine(Source, extractedFileName)))
{
// Check if the file is accessiable.
if (IsAccessible(fi, FileMode.Open, FileAccess.Read))
{
if (!File.Exists(destPath))
{
try
{
File.Copy(sourcePath, destPath);
File.SetAttributes(destPath, FileAttributes.ReadOnly);
// Wait before checking for the file exists at destination.
Thread.Sleep(Convert.ToInt32(ConfigurationManager.AppSettings["ExistsAtDestination"]));
// Check if the file has actually been moved to dest.
if (!File.Exists(destPath))
{
// TODO Raise alarms here.
Trace.WriteLine("Failed to Move. File does not exist in destination. Setting ISS Fault Alarm bit");
//CommonActions.SetAlarmBit(ApplicationConstants.tag_AlarmTag, ApplicationConstants.bit_ISSFault);
// Notify HMI about the error type.
Trace.WriteLine("Failed to Move. File does not exist in destination. Setting ISS File Move Fault Alarm bit");
}
}
catch (Exception ex)
{
// TODO log the exception and Raise alarm?
Trace.WriteLine("Failed to Move or set attributes on file. Setting ISS Fault Alarm bit");
//CommonActions.SetAlarmBit(ApplicationConstants.tag_AlarmTag, ApplicationConstants.bit_ISSFault);
// Notify HMI about the error type.
Trace.WriteLine("Failed to Move or set attributes on file. Setting ISS File Move Fault Alarm bit");
}
}
else
{
Trace.WriteLine("File Move failed as the file: " + newFileName + " already exists in the destination folder");
}
}
else
{
Trace.WriteLine("File Move failed. File is not accessible");
}
}
}
/// <summary>
/// Event which is raised when a file is created in the folder which is being watched.
/// </summary>
/// <param name="sender">Object sender</param>
/// <param name="e">Event arguments</param>
private void fsw_Created(object sender, FileSystemEventArgs e)
{
lock (fswLock)
{
DateTime lastRead = DateTime.MinValue;
DateTime lastWriteTime = File.GetCreationTime(e.FullPath);
if (lastWriteTime != lastRead)
{
eventCount++;
// Start a new task and forget.
Task.Factory.StartNew(() => {
PerformFileActions(e.FullPath);
});
lastRead = lastWriteTime;
}
}
}
/// <summary>
/// Extension method to check if a file is accessible.
/// </summary>
/// <param name="fi">File Info</param>
/// <param name="mode">File Mode</param>
/// <param name="access">File Access</param>
/// <returns>Attempts three times. True if the file is accessible</returns>
private bool IsAccessible(FileInfo fi, FileMode mode, FileAccess access)
{
bool hasAccess = false;
int i = 0;
while (!hasAccess)
{
try
{
using (var fileStream = File.Open(fi.FullName, mode, access))
{
}
hasAccess = true;
i = 1;
break;
}
catch (Exception ex)
{
if (i < 4)
{
// We will swallow the exception, wait and try again.
Thread.Sleep(500);
// Explicitly set hasaccess flag.
hasAccess = false;
i++;
}
else
{
i = 0;
Trace.WriteLine("Failed to Move. File is not accessable. " + ex.ToString());
// Notify HMI
Trace.WriteLine("Failed to Move. File is not accessable.. Setting ISS Fault Alarm bit");
//CommonActions.SetAlarmBit(ApplicationConstants.tag_AlarmTag, ApplicationConstants.bit_ISSFault);
// Notify HMI about the error type.
Trace.WriteLine("Failed to Move. File is not accessable.. Setting ISS File Move Fault Alarm bit");
//CommonActions.SetAlarmBit(ApplicationConstants.tag_AlarmTag, ApplicationConstants.bit_ISSFileCopyFault);
// Explicitly set hasaccess flag.
hasAccess = false;
break;
}
}
}
// return hasAccess;
return true;
}
#endregion
}