0

私のプログラムでは、いくつかのデータを受け取っており、それをファイル (1 つまたは複数) に保存する必要があります。データの順序は非常に重要であるため、先着順に保存する必要があります。

最後に、この時点でデータがもう利用できないという信号を受け取ります。開いているすべてのファイルを閉じる必要があります。どうすれば処理できますか。つまり、すべてのスレッドが作業を完了したことを確認するにはどうすればよいかということです。 、ファイルを閉じることができます。

データの順序を制御するために使用ManualResetEventしているため、次のスレッドは前のスレッドが作業を完了するのを待っています。

以下は私のコードサンプルです。同じ種類の作業を非常に効率的な方法で行うためのガイドラインが必要であり、すべてのスレッドが作業を完了したことをどのように知ることができますか。

class Program
    {
        static StreamWriter _fileStream;
        static void Main(string[] args)
        {
            _fileStream = File.CreateText(@"D:\HelloThread.txt");               
            ManualResetEvent currentEvent = new ManualResetEvent(true);
            ManualResetEvent nextEvent = new ManualResetEvent(false);              
            int length = 60;
            Data data = null;
            Console.WriteLine("Writing started...");
            for (int i = 0; i < length; i++)
            {
                data = new Data { CurrentEvent = currentEvent, Number = i, NextEvent = nextEvent };
                ThreadPool.QueueUserWorkItem(PrintMsg, data);                   
                currentEvent = nextEvent;
                nextEvent = new ManualResetEvent(false);
            }


            Console.ReadLine();
        }

        private static void CloseAll()
        {
            Console.WriteLine("Requested to close all...");


            Console.WriteLine("Done with the writing...");
        }

        private static object _lockObj = new object();

        private static void PrintMsg(object state)
        {
            Data data = state as Data;

            data.CurrentEvent.WaitOne();

            string msg = "Hello times...";
            for (int j = 0; j < 5; j++)
            {
                _fileStream.WriteLine(msg + data.Number);
               // Console.WriteLine(msg + data.Number);
            }

            data.NextEvent.Set();
        }
    }

    public class Data
    {
        public ManualResetEvent CurrentEvent { get; set; }
        public ManualResetEvent NextEvent { get; set; }
        public int Number { get; set; }
    } 
4

1 に答える 1

3

複数のスレッドがあり、それぞれが作業項目の個別の部分に取り組んでいるアプリケーション パイプラインについて説明しているように聞こえます。たとえば、1 つのスレッドが入力を行い、1 つのスレッドが処理を行い、1 つのスレッドが出力を行う場合があります。

通常、これは複数のキューを作成することで処理します。これらの 3 つのスレッドがあるとします。入力スレッドはレコードを読み取り、それを入力キューに入れます。処理スレッドは、入力キューを読み取り、項目を処理して、結果を出力キューに入れます。次に、出力スレッドは出力キューを読み取り、必要な場所にデータを書き込みます。

これにより、作業項目が適切な順序で処理され、書き込まれることが保証されますが、すべてのスレッドが同時に動作することができます。

BlockingCollectionを使用すると、スレッドがキューで非ビジー待機を行うことができます。また、入力スレッドが読み取りを終了するとCompleteAdding、キューを呼び出して、これ以上作業項目がないことを知らせることができます。処理スレッドがキューを読み取ると、IsCompletedプロパティをチェックして、すべての項目が完了したかどうかを判断し、終了することができます。出力キューを読み取るときの出力スレッドについても同じことが言えます。

の簡単な使用例については、http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=821を参照してくださいBlockingCollection

を使用できない場合はBlockingCollection、同時実行レイヤーをラップする必要がありますQueue<T>

于 2012-11-15T15:02:48.923 に答える