1

アプリケーションの起動時に非常に大きな.CSVファイルを読み取り、各行を に変換する必要があるアプリケーションがありますobject。ファイルを読み取るメソッドは次のとおりです。

public List<Aobject> GetAobject()
    {
        List<Aobject> Aobjects = new List<Aobject>();

        using (StreamReader sr = new StreamReader(pathA, Encoding.GetEncoding("Windows-1255")))
        {
            string line;
            while ((line = sr.ReadLine()) != null)
            {
                string[] spl = line.Split(',');
                Aobject p = new Aobject { Aprop = spl[0].Trim(), Bprop = spl[1].Trim(), Cprop = spl[2].Trim() };
                Aobjects.Add(p);
            }
        }

        return Aobjects;
    }

    public List<Bobject> GetBobject()
    {
        List<Bobject> Bobjects = new List<Bobject>();

        using (StreamReader sr =
           new StreamReader(pathB, Encoding.GetEncoding("Windows-1255")))
        {
            //parts.Clear();
            string line;
            while ((line = sr.ReadLine()) != null)
            {
                string[] spl = line.Split(',');
                Bobject p = new Bobject();
                p.Cat = spl[0];
                p.Name = spl[1];
                p.Serial1 = spl[3].ToUpper().Contains("1");
                if (spl[4].StartsWith("1"))
                    p.Technical = 1;
                else if (spl[4].StartsWith("2"))
                    p.Technical = 2;
                else
                    p.Technical = 0;
                Bobjects.Add(p);
            }
        }

        return Bobjects;
    }

これは私を数秒間ブロックしてUIいたので、私はそれを作ろうとしましたmulti-Threaded. ただし、私のすべてのテストでは、un-threadedシナリオの方が高速であることが示されています。これは私がそれをテストした方法です:

 Stopwatch sw = new Stopwatch();
            sw.Start();

            for (int i = 0; i < 1000; i++)
            {
                Dal dal = new Dal();
                Thread a = new Thread(() => { ThreadedAobjects = dal.GetAobject(); });
                Thread b = new Thread(() => { ThreadedBobjects = dal.GetBobject(); });

                a.Start();
                b.Start();

                b.Join();
                a.Join();
            }
            sw.Stop();

            txtThreaded.Text = sw.Elapsed.ToString();

            Stopwatch sw2 = new Stopwatch();
            sw2.Start();

            for (int i = 0; i < 1000; i++)
            {
                Dal dal2 = new Dal();
                NonThreadedAobjects = dal2.GetAobject();
                NonThreadedBobjects = dal2.GetBobject();
            }
            sw2.Stop();

            txtUnThreaded.Text = sw2.Elapsed.ToString();

結果:
スレッド化された実行:00:01:55.1378686
未処理の実行:00:01:37.1197840
用にコンパイルされましたが、リリース モードでは.Net4.0の下でも動作するはずです。 なぜそれが起こるのか、どうすればこれを改善できるのか説明してもらえますか?.Net3.5

4

4 に答える 4

1

を呼び出してから呼び出す単一のスレッドをお勧めしGetAobjectますGetBobject。あなたのタスクはほぼ間違いなく I/O バウンドであり、これら 2 つのファイルが非常に大きく、同じドライブ上にある場合、それらに同時にアクセスしようとすると、多くの不要なディスク シークが発生します。したがって、コードは次のようになります。

ThreadPool.QueueUserWorkItem(() =>
{
    AObjects = GetAObject();
    BObjects = GetBObject();
});

また、同期する必要があるのは 1 つの のみであるため、コードも簡素化されますManualResetEvent

于 2013-10-15T14:30:35.843 に答える
0

このテストを実行すると、毎回わずかに異なる結果が得られます。実行中にコンピューター上で発生する多くのことの影響を受けて、物事が発生するまでにかかる時間 - 例: 他のプロセス、GC など。

しかし、別のスレッドを持つことは、プロセッサがより多くのコンテキスト切り替えを必要とし、すべてのコンテキスト切り替えに時間がかかることを意味するため、結果は合理的です...

context-switch on の詳細を読むことができます: http://en.wikipedia.org/wiki/Context_switch

于 2013-10-15T06:26:41.507 に答える
0

Slugart の正しい答えに追加します。最初のスレッドが完了するのを待つため、並列化は多くの点で効果がありませんが、2 番目のスレッドはより速く完了し、しばらくの間何もしない可能性があります (タスク並列ライブラリと PLINQ を調べてください)。

また、操作は IO バウンドです。これは、並列処理が IO デバイスに依存することを意味します (一部のデバイスは順次実行する方が適切であり、複数の読み取りを実行しようとすると全体的な操作が遅くなります)。

于 2013-10-15T06:38:13.133 に答える