0

DataGridソースへのバインドを使用してObservableCollection、ファイル名とファイルの分析から取得した番号の2つの列を表示しています。

    ObservableCollection<SearchFile> fileso;

    //...

    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        /* Get all the files to check. */
        int dirCount = searchFoldersListView.Items.Count;
        List<string> allFiles = new List<string>();
        for(int i = 0; i < dirCount; i++)
        {
            try
            {
                allFiles.AddRange(Directory.GetFiles(searchFoldersListView.Items[i].ToString(), "*.txt").ToList());
                allFiles.AddRange(Directory.GetFiles(searchFoldersListView.Items[i].ToString(), "*.pdf").ToList());
            }
            catch
            { /* stuff */ }
        }

        /* Clear the collection and populate it with unchecked files again, refreshing the grid. */
        this.Dispatcher.Invoke(new Action(delegate
        {
            fileso.Clear();
            foreach(var file in allFiles)
            {
                SearchFile sf = new SearchFile() { path=file, occurrences=0 };
                fileso.Add(sf);
            }
        }));

        /* Check the files. */
        foreach(var file in allFiles)
        {
            this.Dispatcher.Invoke(new Action(delegate
            {
                int occurences;
                bool result = FileSearcher.searchFile(file, searchTermTextBox.Text, out occurences);

                fileso.AddOccurrences(file, occurences);  // This is an extension method that alters the collection by finding the relevant item and changing it.
            }));
        }
    }

    //...

    public static void AddOccurrences(this ObservableCollection<SearchFile> collection, string path, int occurrences)
    {
        for(int i = 0; i < collection.Count; i++)
        {
            if(collection[i].path == path)
            {
                collection[i].occurrences = occurrences;
                break;
            }
        }
    }

    //...

    public static bool searchTxtFile(string path, string term, out int occurences)
    {
        string contents = File.ReadAllText(path);
        occurences = Regex.Matches(contents, term, RegexOptions.IgnoreCase).Count;
        if(occurences>0)
            return true;
        return false;
    }

    public static bool searchDocxFile(string path, string term, out int occurences)
    {
        occurences = 0;

        string tempPath = Path.GetTempPath();
        string rawName = Path.GetFileNameWithoutExtension(path);
        string destFile = System.IO.Path.Combine(tempPath, rawName + ".zip");
        System.IO.File.Copy(path, destFile, true);

        using(ZipFile zf = new ZipFile(destFile))
        {
            ZipEntry ze = zf.GetEntry("word/document.xml");
            if(ze != null)
            {
                using(Stream zipstream = zf.GetInputStream(ze))
                {
                    using(StreamReader sr = new StreamReader(zipstream))
                    {
                        string docContents = sr.ReadToEnd();
                        string rawText = Extensions.StripTagsRegexCompiled(docContents);
                        occurences = Regex.Matches(rawText, term, RegexOptions.IgnoreCase).Count;
                        if(occurences>0)
                            return true;
                        return false;
                    }
                }
            }
        }
        return false;
    }

    public static bool searchFile(string path, string term, out int occurences)
    {
        occurences = 0;
        string ext = System.IO.Path.GetExtension(path);

        switch(ext)
        {
            case ".txt":
                return searchTxtFile(path, term, out occurences);
            //case ".doc":
            //    return searchDocFile(path, term, out occurences);
            case ".docx":
                return searchDocxFile(path, term, out occurences);
        }
        return false;
    }

ただし、問題は、更新ボタン(上記のdo_workメソッドでワーカーを起動する)を押すと、正しい数値ではなく、数値列にランダムなゼロが表示される場合があることです。何故ですか?数値列を2回更新することに問題があり、実際の更新後に最初のゼロが適用されることがあるためだと思いますが、詳細はわかりません。

4

1 に答える 1

1

これは、変更されたクロージャへのアクセスの場合だと思います

        /* Check the files. */
        foreach(var file in allFiles)
        {
            var fileTmp = file; // avoid access to modified closure
            this.Dispatcher.Invoke(new Action(delegate
            {
                int occurences;
                bool result = FileSearcher.searchFile(fileTmp, searchTermTextBox.Text, out occurences);

                fileso.AddOccurrences(fileTmp, occurences);  // This is an extension method that alters the collection by finding the relevant item and changing it.
            }));
        }

基本的に何が起こっているかというと、ファイル変数をラムダ式に渡していますが、アクションが実際に呼び出される前にファイルが foreach ループによって変更されます。一時変数を使用してファイルを保持すると、これが解決されます。

于 2012-11-13T11:11:36.993 に答える