yield在后台线程中返回IEnumerable

时间:2013-02-18 15:29:34

标签: c# backgroundworker yield

我有以下方法返回目录中的文件列表:

    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对象可用时,它将被提供给调用者。

我已经能够在Back工作器中运行此方法并返回ICollection FileSystemInfo s - 但这会返回整个列表,而我想在找到它们时生成项目

修改

似乎我可能需要重新实现我想要实现的目标(也许这需要回调而不是IEnumerable)

基本上,我希望索引一个Drive值的文件,但我想在后台线程中运行它。这样,我可以逐个文件处理(也许是Dir by Dir),如果需要,我可以在稍后阶段恢复该过程。如此有效,我希望调用者(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
  }
}

1 个答案:

答案 0 :(得分:2)

yield将控制权返回给调用者,直到调用者再次调用枚举数,因此链中的下一个值(如果有)是{{1再次转到来电者

所以我想说,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) {
   ...
}
...

代码不是自然生产的,它仅仅是为了让您了解主题。