我有一个应用程序,它有一个等待事件的主线程(例如,在目录中接收文件)并将该文件发布到API。这部分工作正常。
另一方面,由于某些原因,主线程可能会错过某些文件。所以,我已经设置了一个后台线程,可以在整个应用程序生命周期内运行,清理那些丢失的文件,如下所示:
public virtual void MissedFileHandler()
{
if (_missedFileHandlerThread == null || !_missedFileHandlerThread.IsAlive)
{
_missedFileHandlerThread = new Thread(new ThreadStart(ClearMissedFiles));
_missedFileHandlerThread.IsBackground = true;
_missedFileHandlerThread.Start();
}
}
protected virtual void ClearMissedFiles()
{
while (true)
{
string[] missedFiles = new string[] { };
missedFiles = Directory.GetFiles(ConfigurationHelper.applicationRootDirectory, "*.txt", SearchOption.TopDirectoryOnly);
Parallel.ForEach(missedFiless, (currentMissedFile) =>
{
bool isFileInUse = true;
isFileInUse = FileHelper.CheckIfFileInUse(filesInUseCollection, currentMissedFile)
if (!isFileInUse)
{
bool isHttpTransferSuccess = false;
isHttpTransferSuccess = FileHelper.SendFileToApi(userid, currentMissedFile);
if (isHttpTransferSuccess)
{
File.Delete(currentMissedFile);
}
}
});
Thread.Sleep(1000);
}
}
请注意,由于某些其他原因,将其作为Windows服务或调度程序运行不是一种选择。所以,我确实需要一个后台工作者来定期清理丢失的文件。我查看了Timer
和WaitHandles
,但不太确定如何使用这些来实现以下内容。
两个进程的方式(主要的甚至处理新文件和后台清理器的方法是,在主应用程序线程中,我将实例化类并在应用程序启动时调用方法。它是{{1和Thread.Sleep()
困扰我,正在寻找更好的方法。谢谢。
答案 0 :(得分:3)
您可以使用文件观察程序检测该目录中的新文件。
private void watch()
{
FileSystemWatcher watcher = new FileSystemWatcher();
// Set your path with this
watcher.Path = path;
// Subscribe to event
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
}
答案 1 :(得分:1)
尝试使用Microsoft的Reactive Framework。然后你可以这样做:
IObservable<Unit> fileChanges =
Observable
.Using(() =>
{
var fsw = new FileSystemWatcher();
fsw.Path = path;
fsw.EnableRaisingEvents = true;
return fsw;
}, fsw =>
Observable
.FromEventPattern<FileSystemEventHandler, FileSystemEventArgs>(
h => fsw.Changed += h,
h => fsw.Changed -= h))
.Select(ep => Unit.Default);
IObservable<Unit> periodically =
Observable
.Interval(TimeSpan.FromSeconds(30.0))
.Select(x => Unit.Default);
IObservable<string> clearMissedFiles =
fileChanges
.Merge(periodically)
.SelectMany(u => Directory.GetFiles(ConfigurationHelper.applicationRootDirectory, "*.txt", SearchOption.TopDirectoryOnly))
.Where(f => !FileHelper.CheckIfFileInUse(filesInUseCollection, f))
.SelectMany(f => Observable.Start(() => FileHelper.SendFileToApi(userid, f)), (f, s) => new { file = f, success = s })
.Where(x => x.success)
.Select(x => x.file);
IDisposable subscription =
clearMissedFiles
.Subscribe(f => File.Delete(f));
这会监视文件系统并定期检查。并行调用API,并不会导致O / S一次尝试删除多个文件。
在退出之前,只需致电subscription.Dispose()
进行清理。
NuGet“System.Reactive”用于位,然后引用using System.Reactive.Linq
以显示扩展名。