1

大きなtxtファイルをいくつかの条件でソートするアプリを用意してください。たとえば5つのスレッドを開始する必要がありますが、foreachループを使用してファイルから1行ずつ読み取ります。コードで 5 つのスレッドを開始すると、すべてのスレッドが同じ行になります。

1つのスレッドを開始するコードは次のとおりです。

    Thread[] thr;
    private void button1_Click(object sender, EventArgs e)
    {
        button1.Enabled = false;
        button4.Enabled = true;
        decimal value = 1;
        int i = 0;
        int j = (int)(value);
        thr = new Thread[j];
        for (; i < j; i++)
        {
            thr[i] = new Thread(new ThreadStart(go));
            thr[i].IsBackground = true;
            thr[i].Start();
        }
    }

    private static IEnumerable<string> ReadLineFromFile(TextReader fileReader)
    {
        using (fileReader)
        {
            string currentLine;
            while ((currentLine = fileReader.ReadLine()) != null)
            {
                yield return currentLine;
            }
        }
    }


    public void go()
    {
        while (true)
        {
            TextReader readFile = new StreamReader(file_path, System.Text.Encoding.UTF8, true);
            foreach (string line in ReadLineFromFile(readFile))
            {
                if (line.Split(':')[0].Contains("@"))
                {
                    string out_line = line.Split(':')[0].Replace("+", "") + ":" + line.Split(':')[1];
                    lock (locker)
                    {
                        mail_count++;
                        log_mail(mail_count);
                        mail.Add(out_line.Trim().Replace(";", ":"));
                    }
                }
                else
                {
                    string out_line = line.Split(':')[0].Replace("+", "") + ":" + line.Split(':')[1];
                    lock (locker)
                    {
                        rubbish_count++;
                        log_rubbish(rubbish_count);
                        rubbish.Add(out_line.Trim());
                    }
                }
            }
            MessageBox.Show("Ready");
            BeginInvoke(
            new MethodInvoker(() =>
            {
                button1.Enabled = true;
                button4.Enabled = false;
            }));
            break;
        }
    }
4

3 に答える 3

4

すべてのスレッドが同じファイルを読み取るのは役に立たず、共有ファイルからの読み取りは困難で非効率的です。

メイン関数では、次のようなものが必要になります。

Parallel.ForEach(System.IO.File.ReadLines(file_path, System.Text.Encoding.UTF8), 
   line => ProcessOneLine(line) 
);

その後、ProcessOneLine が実行します.Split(':')

于 2013-06-05T09:49:34.177 に答える
3

通常の生産者と消費者のパターンで行かないのはなぜですか? 1 つのスレッドでファイルを読み取らせ、共有コレクションに行を挿入すると、他のスレッドはコレクションからデータを取得して処理するだけです。

詳細 - ファイルから読み取り、Taskこの行の処理を処理して結果を出力コレクションに入れる行ごとに作成できます。

これは、5 つのスレッドが同じファイルを読み取ろうとし、同じ行を複数回読み取らないよりも優れているようです。

于 2013-06-05T09:49:30.690 に答える
0

パコさんが言っていたことを確認し、拡張したいと思います。他のスレッドは、データを含む共有コレクションのデータを使用して処理する必要があります。

複数のスレッドがテキスト ファイルにアクセスすると、競合状態が発生する可能性があるように思えます。スレッドがファイルを変更しているときに、別のスレッドがそのファイルから読み取りを行っている場合、本質的に予測不可能な結果が生じる可能性があります。

また、過去に、同じテキスト ファイルにアクセスし、それに対して推奨できる複数のスレッドを使用しているときに、BSOD を経験したことがあります。ただし、これに固執する場合は、「ロック」キーワードとシングルトン デザイン パターンを確認することをお勧めします。これにより、一度に 1 つのスレッドのみがファイルにアクセスしていることを確認できます。

関連リンク:

http://msdn.microsoft.com/en-us/library/c5kehkcz(v=vs.80).aspx http://en.wikipedia.org/wiki/Singleton_pattern

http://en.wikipedia.org/wiki/Double-checked_locking

于 2013-06-05T10:35:35.730 に答える