3

私のコードについて助けを求めたいです。私は初心者で、テキスト ファイルへの書き込みで安全なマルチ スレッドを実装したいと考えていました。

    StreamWriter sw = new StreamWriter(@"C:\DailyLog.txt");
    private void Update(){
        var collection = Database.GetCollection<Entity>("products");
        StreamReader sr = new StreamReader(@"C:\LUSTK.txt");
            string[] line = sr.ReadLine().Split(new char[] { ';' });
            while (!sr.EndOfStream)
            {
                    line = sr.ReadLine().Split(new char[] { ';' });
                    t = delegate { 
                           UpdateEach(Convert.ToInt32(line[5])); 
                        }; 
                     new Thread(t).Start();
            }
            sr.Close();

    }
    private void UpdateEach(int stock)
    {
            sw.WriteLine(ean);

    }

コードにエラーはありませんでしたが、すべてがテキスト ファイルに書き込まれているわけではないようです。sw.Close()一部のスレッドがまだ終了していないことがわかっているため、作成しませんでした。sw.Closeさらに、未完了のスレッドがないことを知って実装するにはどうすればよいですか。500 万件のレコードLUSTK.textが読み取られStreamReader、それぞれがスレッドを作成し、各スレッドが同じテキスト ファイルにアクセスします。

4

2 に答える 2

6

異なるスレッドから同じライターに同時に書き込むことはできません。オブジェクトは、同時アクセスをサポートするように設計されていません。

さらに、複数のスレッドから同じファイルに書き込むという一般的な考え方には欠陥があります。物理ディスクはまだ 1 つしかなく、非常に高速にしか回転できません。物事をより速く行うように指示しても、それ以上速く回転することはありません。

それを超えて、あなたが言ったように、ライターを閉じていないため、その結果、バッファーはフラッシュされていません。

また、匿名メソッドが を閉じてlineおり、すべてのメソッドが変化している同じ変数を閉じているというバグもあります。それぞれが変更されない独自の識別子を閉じることが重要です。(これは、ループline で宣言するだけで実現できwhileます。) しかし、最初から複数のスレッドを使用するべきではないため、これに集中する必要はありません。

File.ReadLinesandFile.WriteAllLinesを使用してファイル IO を実行することもできます。これにより、よりクリーンなコードが得られます。

var values = File.ReadLines(inputFile)
    .Select(line => line.Split(';')[5]);
File.WriteAllLines(outputFile, values);

このプロセスを並列化したい場合は、行を読んだ後、行を書き込む前に、各項目で CPU バウンドの作業を行っているためです。前述のように、実際のファイル IO を並列化することは、役に立たず、有害である可能性があります。この場合、CPU バウンドの作業は行を分割して 1 つの値を取得するだけであり、ファイル IO と比較して驚くほど高速になる可能性があります。たとえば、データベースにヒットしたり、各行で高価な処理を行う必要がある場合は、単一のスレッドを介してファイル IO を同期しながら、作業のその部分だけを並列化することを検討します。

于 2013-10-10T19:14:20.360 に答える