0

私は.NETの新しいTPLライブラリを使用していますが、説明できない奇妙な動作に直面しています。私の場合、何らかの理由でネストされたタスクが開始されません。私は私が持っている解決策を次のように単純化しました:

        bool flag = false;

        for (int i = 0; i < 5; i++)
        {
            Task.Factory.StartNew(() =>
                         {
                            while (true) // a lot of newcoming tasks
                            {
                                Thread.Sleep(200); //do some work
                                Task.Factory.StartNew(() =>
                                             {
                                                 flag = true;
                                              });
                            }
                         });
        }

        Thread.Sleep(2000);
        Assert.IsTrue(flag);

同時に実行されている5つのタスクがあります。各タスクは、保留中のキューからいくつかの要素を取得し、いくつかの操作を実行してから、この操作の結果に対してネストされたタスクを実行しようとします。問題は、要素が多すぎて(while(true)がこれをシミュレートしている場合)、5つのタスクすべてが常に実行されている場合、ネストされたタスクが開始されないことです。は、whileループを使用してほとんどのタスクの実行が終了した後にのみ開始できます。

ネストされたタスクの実行をブロックするwhileステートメントに問題があるようですが、何がわかりません:)

4

2 に答える 2

3

Task.Factory.StartNew はタスクを開始しません。スケジュールするタスクのリストにタスクを追加し、スケジューラは次のようなものに基づいていつタスクを実行するかを決定します。使用可能なコアの数 (スレッド プールのサイズ)、現在の CPU 負荷、および既存の作業のスループット。

ここで、タスクのスケジューリングに関するセクションを読む必要があります。

http://parallelpatterns.codeplex.com/releases/view/48562

PDFの63ページ以降。

LongRunning オプションは、スレッド プールを完全にバイパスすることで問題を「修正」します。これには、システムが実際に使用する必要があるよりも多くのスレッドを作成できるという点で、いくつかの欠点があります。これにより、過度のコンテキスト切り替えが発生してパフォーマンスが低下します。

スレッドスリープを使用した上記のコードのような実験は、スケジューラを「だます」ため、誤解を招きます。より多くの作業が追加されていることがわかりますが、CPU 負荷は増加していません.63 スリープを数学を含むタイトなループに置き換える必要があります (たとえば、Sqrt() の計算など)。

キューからアイテムを読み取り、それらをタスクで実行する単一の外部ループを単純に持たないのはなぜですか。こうすることで、アプリケーションは過負荷になることなく、システムの利用可能な並列処理を最大限に活用できます。

次の答えは一見の価値があるかもしれません:

並列タスク ライブラリ WaitAny 設計

于 2010-07-30T23:12:08.283 に答える
0

ライブラリは、使用可能なコアの数に大まかに基づいて並列タスクを開始するだけであることがわかると思います。つまり、CPUよりもかなり多くのスレッドを実際に使用したいI/Oバウンドのタスクには適していません。

ネストされたタスクが開始されないと言っているのではありませんか?あなたは彼らがあなたが望む時点で彼らが始められないが、後で始めると言っているだけです。

于 2010-07-28T11:40:32.443 に答える