C# 在后台线程中生成返回IEnumerable
我使用以下方法返回目录中的文件列表:C# 在后台线程中生成返回IEnumerable,c#,backgroundworker,yield,C#,Backgroundworker,Yield,我使用以下方法返回目录中的文件列表: public IEnumerable<FileInfo> GetFilesRecursiveEnumerable(DirectoryInfo dir) { if (dir == null) throw new ArgumentNullException(); IList<FileSystemInfo> files = new List<FileSystemInfo>();
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;
}
}
}
yield
将控制权返回给调用者,直到调用者再次调用枚举器,因此链中的下一个值(如果有)是yield
再次返回给调用者
所以我想说,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);
}
}
...
}
}
公共IEnumerable GetFilesRecursiveEnumerable(目录信息目录)
{
...
foreach(文件中的文件系统信息x)
{
DirectoryInfo dirInfo=x作为DirectoryInfo;
if(dirInfo!=null)
{
foreach(getFileRecursiveEnumerable(dirInfo)中的FileInfo f)
{
文件准备就绪(f);
}
}
...
}
}
代码不是自然准备好生产的,它只是提供给您一个关于主题的想法。事实是,这将运行得太快,您必须放慢整个过程,以便用户看到更新。这是毫无意义的。而且模式与您需要的不匹配--您需要某种回调,而不是收益。考虑到您必须将每个回调调用封送到UI线程,您最终将在UI线程上运行此方法。省省你自己的烦恼吧。用户不会看到更新,而是我会为文件编制索引。我不希望将整个驱动器的文件传递给调用者,而是希望以增量方式执行这些操作,这样我就可以恢复对驱动器的索引。看起来您面临的是另一个问题。不确定你所说的索引是什么意思,但是你可能想要添加一个描述,描述你实际上想要完成的事情。可能会得到更好的答案。有很多关于这个特定主题的信息,也许你可以根据自己的需要使用其中的一些信息。你需要在后台线程中运行调用这些信息的代码,而不是单独运行这些代码。
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);
}
}
...
}
}