2

以下のコードを検討してください。の複数のインスタンスを作成したくありませんclass Waiter。(したがって、ManualResetEventクラスは使用できません)

using System;
using System.Threading;

    public class Waiter
    {
        static int counter=0;
        static int max=20;

        public void Start()
        {
            for (int i = 1; i <= max; i++)
            {
                ThreadPool.QueueUserWorkItem(DoWork, (object)i);

            }
            Console.Read();//without this line the application quits before all threads are complete :(

        }

        public void DoWork(object o)
        {
            try
            {
                Thread.Sleep(1000);

            }
            finally
            {
                counter++;
                Console.WriteLine(counter);
                if (counter==max )
                {
                    Console.WriteLine("All threads complete");
                }
            }



        }

    }

    public class ThreadPoolExample
    {
        static void Main()
        {

            Waiter wtr=new Waiter();
            wtr.Start();



        }
    }

上記のコードに2つの問題があります

1>アプリケーションがないと、 Console.Read()すべてのスレッドが終了する前にアプリケーションが終了します。

2>ステートメント Console.WriteLine("All threads complete");が2回実行されます。

これを修正するにはどうすればよいですか?

4

2 に答える 2

3

代わりにタスクを使用すると、 Task.WaitAll(tasks);を実行できます。

また、ファクトリを介してタスクをインスタンス化します。

Task.Factory.StartNew(() => { Console.Writeline(""); });

スレッドプールを使用します。

于 2012-05-25T15:35:20.980 に答える
0

Interlocked.Incrementを使用してインクリメントする必要がありますcounter。現状では、2つのスレッドが同時にインクリメントしようとすると競合状態が発生します。

Writer同時に動作する複数のインスタンスが必要な場合は、静的counter変数を使用することはできません。彼らはお互いに戦うでしょう。プライベートインスタンス変数にするだけで問題ありません。Maxは、変更されない場合はconstまたはreadonly(および静的なまま)である必要があり、変更される可能性がある場合はインスタンスフィールドでもある必要があります。

最後に、非静的ManualResetEventインスタンスがある場合は、インスタンスを作成しStart、初期化して設定し、ループの最後で待機してから、最後のスレッドが終了したときにシグナルを送信します(現在コンソールに書き込むだけです)。 )。

于 2012-05-25T16:00:44.173 に答える