2

ディレクトリ内のファイルのリストを返すには、次のメソッドがあります。

    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オブジェクトが使用可能になったときに呼び出し元に渡されるようにします。

このメソッドをBackgroundワーカーで実行し、sを返すことができましたICollectionFileSystemInfo、リスト全体が返されますが、見つかったアイテムを生成したいと思います。

編集

達成しようとしていることを再評価する必要があるようです(おそらく、これはIEnumerableではなくコールバックを必要とします)

基本的に、ドライブに相当するファイルのインデックスを作成したいのですが、これをバックグラウンドスレッドで実行したいと思います。そうすれば、ファイルごとに(おそらく、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
  }
}
4

1 に答える 1

2

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

コードは自然に本番環境に対応しているわけではなく、主題に関するアイデアを提供するためだけに提供されています。

于 2013-02-18T15:37:33.580 に答える