0

MSDN for.NETThreadPoolにサンプルがあります。このコードを実行すると、出力が完全に不安定になり、コンソールに完全に空の出力が表示されることがあります。

呼び出しを追加するThread.Sleep()と、ほんの数ミリ秒でも、出力は正常です。

AFAIKConsole.WriteLine()はスレッドセーフであるため、出力は常にそこにある必要があります。しかし、少なくとも私のi7 2600 x64コンパイル済みバージョンではそうではありません。明らかに、ブレークポイントを追加すればすべて問題ありませんが、それは私を怒らせます。

ConcurrentBagを追加して、内容が確実に含まれるようにしましたが、その要素を印刷することもできません。繰り返しますが、ブレークポイントを追加すると、すべて問題ありません。

{
    public class TaskInfo
    {
        public string m_text;

            public int m_value;
        public ConcurrentBag<int> m_bag;
    public TaskInfo(string text, int value, ConcurrentBag<int> bag)
    {
        m_text = text;
        m_value = value;
        m_bag = bag;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Program p = new Program();
        p.Run();
    }

    void Run()
    {
        ConcurrentBag<int> concurrentBag = new ConcurrentBag<int>();
        for (int i = 0; i < 10; i++)
        {
            TaskInfo ti = new TaskInfo("Hello Thread", i, concurrentBag);
            bool b = ThreadPool.QueueUserWorkItem(new WaitCallback(MyThreadFunction), ti);
            if (!b)
            {
                Console.WriteLine("Damn!");
            }
            //Thread.Sleep(5);
        }

        for (int j = 0; j < concurrentBag.Count; j++)
        {
            Console.WriteLine("This is in the bag: {0}", concurrentBag.ElementAt(j));
        }
    }

    static void MyThreadFunction(object stateInfo)
    {
        TaskInfo ti = (TaskInfo)stateInfo;
        ti.m_bag.Add(ti.m_value);
        Console.WriteLine(ti.m_text + ti.m_value.ToString());
    }
}

}

4

3 に答える 3

1

これは明らかにコンソールアプリケーションです。すべての作業項目をキューに入れると、Runメソッドが戻り、プログラムはすぐに終了します。作業項目が終了するのを待つことはありません。少なくとも、Thread.Sleep実行後にアフターを追加して、スレッドプールを完了できるようにします。

正しいことは、インスタンスの配列を使用して、それらがすべて各ワーカースレッドによって実行さManualResetEventれるのを待つことです。これはコンソールアプリケーションであるため、メソッドをで装飾しない限りSet使用できません。WaitHandle.WaitAllMain[STAThread]

于 2011-12-18T20:14:43.657 に答える
1

出力が空になる可能性があることはよく理解できます。

10個のジョブをキューにプッシュすると、すぐに結果の消費を開始します。すべての仕事が終了するわけではなく、まだ開始されていない可能性もあります。

また、デバッガーで実行すると、MyThreadFunctionからWrtieLine()が表示される前に、プログラムが終了します。

于 2011-12-18T20:15:04.783 に答える
0

スレッドを作成するときは、スレッドによって「生成された」ものを印刷しようとするまで、スレッドに参加する必要がありますか(スレッドが終了するまで待ちます)。

そうでない場合は、最後のループの前にスレッドを切り替えることができるスケジューラーに依存していRunます。そうでない場合、最後のループは、スレッドが開始する前に実行されます。

一方、スケジューラーをすぐに他のスレッドに切り替えられるようにします。これが、内部にThread.Sleep問題がないことを確認できる理由です。Thread.Sleep

于 2011-12-18T20:14:25.033 に答える