Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在后台线程中生成返回IEnumerable_C#_Backgroundworker_Yield - Fatal编程技术网

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);
            }
        }
        ...
    }
}