在后台线程中产生返回IEnumerable
本文关键字:返回 IEnumerable 后台 线程 | 更新日期: 2023-09-27 18:00:02
I有以下方法返回目录中的文件列表:
public IEnumerable<FileInfo> GetFilesRecursiveEnumerable(DirectoryInfo dir)
{
if (dir == null) throw new ArgumentNullException();
IList<FileSystemInfo> files = new List<FileSystemInfo>();
try
{
files = dir.GetFileSystemInfos();
}
catch (UnauthorizedAccessException) { } //ignore
catch (PathTooLongException)
{
MessageBox.Show("Path too long in directory: " + dir.FullName);
}
foreach (FileSystemInfo x in files)
{
DirectoryInfo dirInfo = x as DirectoryInfo;
if (dirInfo != null)
{
foreach (FileInfo f in GetFilesRecursiveEnumerable(dirInfo))
{
yield return f;
}
}
else
{
FileInfo fInfo = x as FileInfo;
if (fInfo != null) yield return fInfo;
}
}
}
此方法会阻塞GUI。我想在后台线程(仅限单个线程)中运行此操作,以便在FileSystemInfo
对象可用时将其提供给调用者。
我已经能够让这个方法在后台工作程序中运行,并返回一个ICollection
s的CCD_2,但这会返回整个列表,而我希望在找到项目时生成它们。
编辑
看起来我可能需要重申我想要实现的目标(也许这需要回调而不是IEnumerable)
本质上,我希望索引相当于Drive的文件,但我希望在后台线程中运行它。这样,我可以一个文件接一个文件地处理(可能是一个目录接一个目录),如果需要的话,我可以在稍后阶段继续处理。因此,实际上,我希望调用方(GUI线程)运行此方法,但在目录扫描期间得到通知,而不是在它完全完成时。例如,
//My original thoughts, but maybe need to tackle this a different way
public void ScanDrive()
{
foreach(FileInfo f in GetFilesRecursiveEnumerable())
{
//index file
//record the directory I am up to so I can resume later
/Keeping my application responsive to perform other tasks
}
}
yield
将控制权返回给调用方,直到调用者再次调用枚举器,因此链中的下一个值(如果有)是yielded
,再次返回给调用者。
所以我想说,yield
本身不符合您的要求。为了实现您的想法,您可以使用简单的线程同步,其中调用者(主线程)在另一个线程上调用一个返回下一个文件信息的方法。
或者简单地使用一些"回调机制":
简单示例:
void Main() {
//start thread
Thread t = new Thread(GetFilesRecursiveEnumerable)
t.Start(..);
}
//called by thread as soon as FileInfo is ready
void FileReady(FileInfo fi) {
...
}
...
方法内部:
public IEnumerable<FileInfo> GetFilesRecursiveEnumerable(DirectoryInfo dir)
{
...
foreach (FileSystemInfo x in files)
{
DirectoryInfo dirInfo = x as DirectoryInfo;
if (dirInfo != null)
{
foreach (FileInfo f in GetFilesRecursiveEnumerable(dirInfo))
{
FileReady(f);
}
}
...
}
}
这段代码自然还没有准备好生产,提供它只是为了让您对这个主题有一个想法。