0

プログレスバーとマルチスレッドに関する多くの質問と投稿を既に目にしているので、他の場所で既に回答されている質問をしていないことを願っています. しかし、もしそうなら、申し訳ありませんが、解決策を見つけようとしました。

& を & に置き換えたい大きなファイルがいくつかあります。これらのファイルは大きいため、ときどき statusupdate を表示して、ドキュメントがどこまで解析されたかを確認したいと考えています。私が書いたコードは、アンパサンドを置き換える目的で機能しますが、進行状況の更新は、ドキュメントが解析された後にのみ行われます。何が問題なのですか?

using System;
using System.Windows;
using Microsoft.Win32;
using System.Text;
using System.Xml;
using System.IO;
using System.Diagnostics;
using System.Data.SqlClient;
using System.Data;
using System.Text.RegularExpressions;
using System.ComponentModel;

namespace DigiPort
{
    public partial class MainWindow : Window
    {

        public string filename;
        public string xmlfilename;
        BackgroundWorker worker = new BackgroundWorker();

        public MainWindow()
        {
            InitializeComponent();
        }

        private void onImportDocClicked(object sender, RoutedEventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "Text documents (.txt)|*.txt";
            Nullable<bool> result = ofd.ShowDialog();
            if (result == true)
            {
                OutPutWindow.Text = "Document wordt nu gelezen.";
                filename = ofd.FileName;
                worker.DoWork += new DoWorkEventHandler(ReplaceAmpersandAsync);
                worker.ProgressChanged += new ProgressChangedEventHandler(ProBarChanged);
                worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(ReplaceAmpersandCompleted);
                worker.WorkerReportsProgress = true;
                worker.ReportProgress(0, "Start counting lines");
                int count = ReadNumberOfLines();
                worker.ReportProgress(0, "Lines counted. Total number of lines is: " + count);
                worker.RunWorkerAsync(count);
                OutPutWindow.Text = "Document gelezen en ampersands vervangen.";
            }
        }

        private int ReadNumberOfLines()
        {
            int count = 0;
            using (FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            using (BufferedStream bs = new BufferedStream(fs))
            using (StreamReader sr = new StreamReader(bs))
                while (!sr.EndOfStream)
                {
                    sr.ReadLine();
                    count++;
                }
            return count;
        }

        private void ReplaceAmpersandAsync(object sender, DoWorkEventArgs e)
        {
            int i = 0;
            int count = (int)e.Argument;
            xmlfilename = filename + ".xml";
            StreamWriter writer = new StreamWriter(xmlfilename);
            using (FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            using (BufferedStream bs = new BufferedStream(fs))
            using (StreamReader sr = new StreamReader(bs))
            while (!sr.EndOfStream)
            {
                double percentage = (i++ * 100) / count;
                worker.ReportProgress((int)Math.Round(percentage, 0));
                if (i % 100000 == 0)
                {
                    worker.ReportProgress(i, "Linenumber " + i + " is now parsed");
                }
                string content = sr.ReadLine();
                writer.WriteLine(content.Replace("&", "&amp;"));
            }

            writer.Close();
            worker.ReportProgress(i, "All lines are parsed, file is saved");
        }

        private void ProBarChanged(object sender, ProgressChangedEventArgs e)
        {
            ProBar.Value = e.ProgressPercentage;
            OutPutWindow.Text += (string)e.UserState;
        }

        private void ReplaceAmpersandCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
        }
    }
}
4

1 に答える 1

3

また、あまりにも多くのイベントを発生させています。解析されるすべての行に対してイベントを発生させるべきではありません。これにより、Windowsのメッセージキューがいっぱいになり、追いつくことができなくなります。重要な進歩があるたびにのみイベントを発生させます(たとえば、1%完了するごとにイベントを発生させます)。

また、ReportProgressの最初の引数は、作業の完了度を表す0から100までのパーセンテージであると想定されています。ここでは、行番号を返すためにそれを誤用しています。

worker.ReportProgress(i, "Linenumber " + i + " is now parsed");

また、コードが生成する可能性のある例外を現在飲み込んでいることにも言及する価値があります。完了したイベントハンドラーで、エラーが発生したかどうかを確認する必要があります。

private void ReplaceAmpersandCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error != null) {
        // Show the user an error message.
    }
}
于 2013-03-19T16:07:21.013 に答える