この記事は機械翻訳のミラー記事です。元の記事にジャンプするにはこちらをクリックしてください。

眺める: 42759|答える: 5

[出典] なぜ.net/c#のタスクはThreadよりも遅いのですか?

[リンクをコピー]
掲載地 2017/05/03 16:40:28 | | | |
.NET 4には新しい名前空間System.Threading.Tasksが含まれており、スレッド機能を抽象化するクラスが含まれています。 バックグラウンドでThreadPoolを使いましょう。 タスクは、完成すべきユニットの作業を表します。 このユニットの作業は別のスレッドで実行することも、同期的にタスクを開始することもでき、メインのチューニングスレッドを待つ必要があります。 タスクを使うことで抽象化レイヤーができるだけでなく、基盤となるスレッドに対して多くのコントロールも得られます。
タスクは、必要な作業のスケジュール調整において非常に柔軟性があります。 例えば、継続的タスクを定義できます。タスク完了後に行うべき作業を。 これが成功するかどうかを分けることもあります。 さらに、タスクは階層構造で配置可能です。 例えば、親タスクは新しい子タスクを作成することができます。 これにより依存関係が生まれ、親タスクをキャンセルすると子タスクもキャンセルされます。


現在ではタスク実行メソッドを使うことが人気で、高性能ですが、タスクのパフォーマンスがどこにあるのかはわかりません。

私自身もTaskとThreadをテストしましたが、Taskは非常に遅く、それがパフォーマンスに大きく影響していると感じました。テストコードは以下の通りです:

このメソッドを1000回ループし、その後メソッドは100ミリ秒間ブロックし、テスト結果は以下の通りです。



結果:
スレッド実行は188ミリ秒かかります
タスク実行には14,671ミリ秒かかります


両者の速度差は78倍です!!

タスクが非常に遅いのですが、なぜこうなるのか分かりません。テストコードに何か問題があるのでしょうか? なぜこうなるのか説明してもらえるといいですね...




先の:ASP.NET Coreでメッセージを送信
次に:C# 並列計算 Parallel.For&Parallel.For
 地主| 掲載地 2020/10/13 10:47:17 |
tongli1996218 2020-10-13 09:34に投稿
Threadと同じコードを確保するために、私の操作は以下のコードで、上記は疑似コードです
追伸:Task.Delayを「wait.delay」と呼んでください。追加しなくても...

はいありがとうございます

タスク実行時間:117.0357

コードは以下のように変更できます:

Task.RunはTask.Factory.StartNewの代わりになり、内部タスクを自動的に解凍します。
Task.WaitAllは内部タスクではなく外部タスクを待機します。 Task.Runを使うとネストされたタスクはありません。


msdnのドキュメントを見ると、Task.Delayメソッドは指定されたミリ秒後に完了するタスクを生成することがわかります。 (実際には新しいスレッドが作成され、タスクの実行を待つためにawaitが追加されますが、正しく理解していません)

ハイパーリンクのログインが見えます。

さらに、タスクと虚無には違いがあります

タスクは待機可能な非同期メソッドを返します
voidリターンの非同期メソッドは待てません。非同期で動作しますが、完了時はわからず、非同期操作の状態を監視することもできません。


参考:

ハイパーリンクのログインが見えます。
ハイパーリンクのログインが見えます。

まとめると:コードに問題があり、Taskメソッド内でThread.Sleepを使うべきではありません
掲載地 2020/07/21 13:09:29 |
今日も同じ問題がありました。AES暗号化にマルチスレッドを使っていますが、TaskはThreadよりもずっと遅いです!!
大家さんは理由を見つけましたか?
掲載地 2020/10/12 19:24:48 |
この投稿はtongli1996218によって2020年10月12日19:43に最終編集されました。

所有者のコードをテストした後、プログラムを何度も起動・実行すると、タスクの時間はさらに短くなり、私のパソコンではThreadより短く、Threadはその期間内は安定しています。

後に、Thread.Sleep(100)メソッドはタスクには悪影響を与えるものの、スレッドには影響を与えず、Thread.Sleep(100)は数値自己加算やawait Task.Delay(100)など、他の時間のかかるプログラム検証に置き換えることができました。

追伸:Thread.Sleepは呼び出し後に現在のスレッドスライシング時間を終了します。例えばThread.Sleep(0)は現在のスレッドスライシング時間を終了し、他のスレッドに転送して実行させます。 タスク内にはスレッドプールがあり、スレッドのコンテキスト切り替えを最適化し、CPU損失時間を削減できます(特にマルチコアCPU最適化の場合)。一方、Thread.Sleep(100)はタスクの元のスレッドプールのスイッチングロジックを妨害し、多くのCPU時間損失を引き起こします

Thread.Sleep(100)をawait Task.Delay(100)に置き換えると、タスクの時間消費時間は100ミリ秒を超えません。以下のように示されています。
private void TaskTest()
{
        Thread.Sleep(100);
         ... 行動を起こしてください
}
置き換え
private async void TaskTest()
{
      待機。遅延(100);
      ... タスクの実行時間は100ミリ秒以上で、これは元のThread.Sleep(100)と同じです
}




 地主| 掲載地 2020/10/12 22:53:05 |
tongli1996218 2020-10-12 19:24 に投稿
所有者のコードをテストした後、プログラムが起動されると、何度も実行するとタスクの時間がさらに短くなり、私のコンピュータではスレッドより短くなってしまいます...

こういうコードに変更してみました:
Task.Delay(100000);

タスク実行時間:14.1306 ms、全体の時間は非常に短いですが、タスクが呼び出すメソッドは実行を完了しませんでした。
掲載地 2020/10/13 9:34:33 |
この投稿は2020年10月13日 09:40 に tongli1996218 によって最後に編集されました
2020年10月12日 22:53公開
こういうコードに変更してみました:
タスク遅延(100000);

Threadと同じコードを確保するために、私の操作は以下のコードで、上記は疑似コードです
追伸:waitit、Task.Delayを呼び出して、コードを追加せずに、タスクが開いたスレッドは即座に返されます。計算バウンドのシミュレーションを確実にするために、(int a = 0; a<1000000; ++a){}; そのような方法を代わり

private async static void TaskTest()
        {
            待機。遅延(100000);
             インターロックド。インクリメント(参照ラン);    ロックはかかりますが、オーバーヘッドは小さいです
            if(run == j)
             {
                ストップウォッチ。 Stop(); 監視をやめろ
                タイムスパン タイムスパン = ストップウォッチ。 経過;  現在のインスタンスで測定された合計時間を取得します
                Console.WriteLine("タスク実行時間:" + 時間。 TotalMilliseconds); 総ミリ秒
              }
        時間も非常に短いです


免責事項:
Code Farmer Networkが発行するすべてのソフトウェア、プログラミング資料、記事は学習および研究目的のみを目的としています。 上記の内容は商業的または違法な目的で使用されてはならず、そうでなければ利用者はすべての結果を負うことになります。 このサイトの情報はインターネットからのものであり、著作権紛争はこのサイトとは関係ありません。 ダウンロード後24時間以内に上記の内容を完全にパソコンから削除してください。 もしこのプログラムを気に入ったら、正規のソフトウェアを支持し、登録を購入し、より良い本物のサービスを受けてください。 もし侵害があれば、メールでご連絡ください。

Mail To:help@itsvse.com