タスクとスレッドの違いは何ですか?


378

C#4.0ではTaskSystem.Threading.Tasks名前空間にあります。間の真の違いは何であるThreadとはTask。私は自分で学ぶためにいくつかのサンプルプログラム(MSDNから取ったヘルプ)をしました

Parallel.Invoke 
Parallel.For 
Parallel.ForEach 

しかし、アイデアがあまり明確ではないため、多くの疑問があります。

Stackoverflowで同様の種類の質問を最初に検索しましたが、この質問のタイトルでは同じ結果を得ることができなかった可能性があります。同じ種類の質問が以前にここに投稿されていることを誰かが知っている場合は、リンクのリファレンスを提供してください。


8
スレッドがタスクを実行する
pm100

回答:


314

タスクはあなたがしたいことです。

スレッドは、そのタスクを実行する多くの可能なワーカーの1つです。

.NET 4.0の用語では、タスクは非同期操作を表します。スレッドは、作業をチャンクに分割し、個別のスレッドに割り当てることにより、その操作を完了するために使用されます。


タスクを完了するために機能するスレッドの基本的な例を提供できますか?スレッドが相互に独立した作業を行っているのか、それともチームワーク計算を行っているのかわかりません。
pensum

両方のシナリオが可能です。最適な状況では、スレッドは他のスレッドと同期する必要なく独立した作業を行います。実際には、ロックはスレッドを調整するために使用されます。
ミッチ小麦

451

コンピュータサイエンス用語でTaskは、a は未来または約束です。(一部の人々はsynomymously、いくつかの使用は、それらが異なって、誰もが同意することはできませんこれら二つの用語を使用し、正確な、基本的な定義。)Task<T>あなた返すように「約束」Tではなく、今は蜂蜜ない理由、私は、ちょっと忙しいです後で戻ってくるの?

A Threadはその約束を果たす方法です。しかし、すべてTaskが真新しいものを必要としているわけではありませんThread。(実際、スレッドを作成することは望ましくありません。スレッドプールから既存のスレッドを再利用するよりもはるかにコストがかかるためです。その詳細については、後で詳しく説明します。)待機している値がファイルシステムまたはデータベースまたはネットワークであれば、他の要求にサービスを提供できるときに、スレッドが座ってデータを待つ必要はありません。代わりに、Task準備が整ったときに値を受け取るコールバックを登録する場合があります。

具体的には、Taskないではないと言う理由は、それが値を返すために、このような長い時間がかかるということです。それは可能性がある、それは計算するのに長い時間を要することになり、またはそれがフェッチするのに長い時間がかかることがあります。前者の場合のみ、を使用してThreadを実行しTaskます。(.NETでは、スレッドは非常に負荷が高いため、通常はできるだけスレッドを回避し、複数のCPUで複数の重い計算を実行する場合にのみ実際に使用します。たとえば、Windowsでは、スレッドの重量は12 KiByte( Linuxでは、スレッドの重量はわずか4 KiByte、Erlang / BEAMでは、わずか400バイトです。.NETでは、1 MiByteです!)


29
興味深いことに、TPL(Task Parallel Library)の初期プレビューリリースでは、Task and Future <T>がありました。その後、Future <T>はTask <T>に名前が変更されました。:)
リーキャンベル、

23
.NETの1 MBをどのように計算しましたか?
dvallejo

5
@DanVallejo:その数はTPL設計チームへのインタビューで言及されました。誰が言ったのか、どのインタビューだったのかはわかりません。その年前に見ました。
イェルクWミッターク

9
@RIPUNJAYTRIPATHIもちろん、別のスレッドである必要はありません。最初に作業を要求したスレッドである可能性があります。
Chris Pitman 2013年

7
.NETはWindowsでWindowsスレッドを使用するだけなので、サイズは同じです。デフォルトでは、通常、両方に1 MiBの仮想メモリが使用されます。物理メモリは、ネイティブコードと同じように、ページサイズのチャンク(通常64 KiB)で必要に応じて使用されます。最小スレッドスタックサイズはOSによって異なります-たとえば、Vistaでは256 KiB。x86 Linuxでは、デフォルトは通常2 MiBです。これも、ページサイズのチャンクで割り当てられます。(簡略化)Erlangはプロセスごとに1つのシステムスレッドのみを使用します。これらの400バイトは.NETに似たものを参照しますTask
Luaan

39

ベアメタルのことで、おそらくそれを使用する必要はありません。LongRunningタスクを使用して、.NET Framework 4(2002年2月)以降(.NET芯)。

タスク

スレッドの上の抽象化。これは、スレッドプールを使用しています(あなたは、タスクを指定しない限り、LongRunningそうならば、新しいスレッドがあなたのためにボンネットの下に作成された操作)。

スレッドプール

名前が示すように:スレッドのプール。限られた数のスレッドを処理する.NETフレームワークですか。どうして?100スレッドを開いて、コアが8つしかないプロセッサで高価なCPU演算を実行することは、決して良い考えではないからです。フレームワークはこのプールを維持し、スレッドを再利用し(各操作でスレッドを作成/殺さない)、CPUが燃えないようにスレッドのいくつかを並行して実行します。

わかりましたが、それぞれをいつ使用するのですか?

再開時:常にタスクを使用します。

タスクは抽象化なので、非常に使いやすくなっています。常にタスクを使用することをお勧めします。スレッドを自分で(おそらく1%の時間で)処理する必要がある問題に直面した場合は、スレッドを使用してください。

ただし、次のことに注意してください。

  • I / Oバウンド:I / Oバウンド操作(データベース呼び出し、読み取り/書き込みファイル、API呼び出しなど)の場合は、通常のタスクの使用を避け、LongRunningタスク(または必要に応じてスレッド)を使用します。タスクを使用すると、いくつかのスレッドがビジーで、別の多くのタスクがプールを取得する順番を待っているスレッドプールにつながるからです。
  • CPUバウンド:CPUバウンド操作の場合、通常のタスク(内部的にはスレッドプールを使用します)を使用するだけで十分です。

わずかな修正ですが、スレッドは「ベアメタル」ではありません。OSによって実装され、ほとんどの実装はCPUとCSの機能を中継しますが、ハードウェアによって実装されません。
Tomer W

7

を使用Taskして何をしたいかを指定Taskし、それをThread。そのため、GUIスレッドではなく、Task新しく作成されたThreadスレッドで実行されます。

で使用TaskしますTaskFactory.StartNew(Action action)。ここではデリゲートを実行するため、スレッドを使用しなかった場合は同じスレッド(GUIスレッド)で実行されます。スレッドについて言及する場合は、これTaskを別のスレッドで実行できます。これは不要な作業です。デリゲートを直接実行するか、そのデリゲートをスレッドにアタッチして、そのスレッドでデリゲートを実行できます。したがって、使用しないでください。それは単に不要です。ソフトウェアを最適化するつもりなら、これは削除するのに適した候補です。

** Actionはであることに注意してくださいdelegate


6

上記の点に加えて、次のことを知っておくとよいでしょう。

  1. タスクはデフォルトでバックグラウンドタスクです。フォアグラウンドタスクを持つことはできません。一方、スレッドはバックグラウンドまたはフォアグラウンドにすることができます(動作を変更するには、IsBackgroundプロパティを使用します)。
  2. スレッドプールで作成されたタスクは、リソースを節約するのに役立つスレッドをリサイクルします。したがって、ほとんどの場合、タスクがデフォルトの選択になります。
  3. 操作が速い場合は、スレッドの代わりにタスクを使用する方がはるかに優れています。長時間実行される操作の場合、タスクはスレッドに比べて多くの利点を提供しません。

4

私は通常Task、Winformsおよび単純なバックグラウンドワーカーとやり取りして、UIがフリーズしないようにするために使用します。ここで私が使用したい例Task

private async void buttonDownload_Click(object sender, EventArgs e)
{
    buttonDownload.Enabled = false;
    await Task.Run(() => {
        using (var client = new WebClient())
        {
            client.DownloadFile("http://example.com/file.mpeg", "file.mpeg");
        }
    })
    buttonDownload.Enabled = true;
}

VS

private void buttonDownload_Click(object sender, EventArgs e)
{
    buttonDownload.Enabled = false;
    Thread t = new Thread(() =>
    {
        using (var client = new WebClient())
        {
            client.DownloadFile("http://example.com/file.mpeg", "file.mpeg");
        }
        this.Invoke((MethodInvoker)delegate()
        {
            buttonDownload.Enabled = true;
        });
    });
    t.IsBackground = true;
    t.Start();
}

違いは、使用する必要のないMethodInvokerコードと短いコードです。


4

タスクは実行したい操作のようなもので、スレッドは複数のプロセスノードを介してそれらの操作を管理するのに役立ちます。スレッド化は複雑なコード管理
につながる可能性があるため、タスクは軽量なオプションです。常にMSDNから読むことをお勧めします(世界最高)

タスク


3

タスクは、何かを非同期および並列に実行する便利で簡単な方法と見なすことができます。

通常、必要なのはタスクだけですが、実験以外の目的でスレッドを使用したことがあるかどうかは思い出せません。

タスクの場合と同じように、スレッドを使用して(多くの労力で)同じことを実行できます。

int result = 0;
Thread thread = new System.Threading.Thread(() => { 
    result = 1; 
});
thread.Start();
thread.Join();
Console.WriteLine(result); //is 1

仕事

int result = await Task.Run(() => {
    return 1; 
});
Console.WriteLine(result); //is 1

タスクはデフォルトでThreadpoolを使用します。これは、スレッドの作成にはコストがかかるため、リソースを節約します。タスクは、スレッドの上位レベルの抽象化として見ることができます。

この記事が指摘すると、タスクはスレッドを超える強力な機能以下の提供します。

  • タスクは、マルチコアプロセッサを活用するために調整されます。

  • システムに複数のタスクがある場合、システムはCLRスレッドプールを内部で使用するため、スレッドを使用して専用スレッドを作成することに関連するオーバーヘッドがありません。また、複数のスレッド間のコンテキスト切り替え時間を短縮します。

  • タスクは結果を返すことができます。スレッドから結果を返す直接のメカニズムはありません。
  • シグナリング構造なしで、一連のタスクを待ちます。

  • タスクをチェーンして次々に実行できます。

  • あるタスクが別のタスクから開始されたときに親子関係を確立します。

  • 子タスクの例外は親タスクに伝播する可能性があります。

  • タスクは、キャンセルトークンを使用してキャンセルをサポートします。

  • 非同期の実装は、「async」および「await」キーワードを使用して、タスクが簡単です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.