web-dev-qa-db-ja.com

.NET4でのマルチスレッドの改善

.NET 4チームがフレームワークに新しいクラスを追加して、スレッドの操作をより良く、より簡単にすると聞いています。

基本的に問題は、.NET 4で追加されたマルチスレッドタスクを実行するための新しい方法と、それらが使用されるように設計されているものは何かということです。

PD:明確にするために、私は.NET 4で並列タスクを実行する単一の方法を探していません。これは新しく追加されたものであり、可能であれば、それぞれそれぞれが最適です。

28
Artiom Chilaru

回答がなかったので、私が学んだことで以下の回答を評価することにしました。@ Scottが述べたように、.NET 4は、並列処理に多くの革新、新しい方法、アプローチを追加するタスク並列ライブラリを追加しました。

  • 最初に言及することの1つは、Parallel.ForメソッドとParallel.ForEachメソッドです。これにより、開発者は複数のスレッドで複数のアイテムを処理できます。この場合のフレームワークは、必要なスレッドの数、新しいスレッドを作成するタイミング、作成しないタイミングを決定します。
    これは、既存のコードを並列化し、パフォーマンスを向上させる非常にシンプルで簡単な方法です。
  • 別の方法は、以前のアプローチと多少似ていますが、PLINQエクステンダーを使用することです。それらは既存の列挙を取り、並列linqエクステンダーでそれを拡張します。したがって、既存のlinqクエリがある場合は、それをPLINQに簡単に変換できます。これが意味するのは、列挙可能なPLINQのすべての操作も複数のスレッドを利用し、たとえば.Where句を使用してオブジェクトのリストをフィルタリングすると、複数のスレッドで実行されるようになります。
  • TPLの大きな革新の1つは、新しいTaskクラスです。いくつかの点で、すでによく知られているThreadクラスのように見えるかもしれませんが、.NET 4の新しいスレッドプール(以前のバージョンと比較して大幅に改善されています)を利用しており、はるかに機能的です。通常のThreadクラスより。たとえば、チェーンの途中のタスクが前のタスクが終了したときにのみ開始されるタスクをチェーンできます。 チャンネル9 のスクリーンキャストでの例と詳細な説明
  • タスククラスでの作業を強化するために、BlockingCollection<>を使用できます。これは、生産者/消費者シナリオがある状況で完全に機能します。複数のスレッドでいくつかのオブジェクトを生成し、それをコンシューマーメソッドによって消費および処理することができます。これは、タスクファクトリとブロッキングコレクションを使用して簡単に並列化および制御できます。 チャンネル9 の例を含む便利なスクリーンキャスト
    これらは、さまざまなバッキングストレージクラス(ConcurrentQueue、ConcurentStack、ConcurrentBag)を使用することもできます。これらはすべてスレッドセーフであり、要素の順序とパフォーマンスの点で異なります。別の例と説明 ビデオはこちら
  • 追加されたもう1つの新しいもの(おそらくTPLの一部ではありませんが、とにかくここで役立ちます)は、「タスク調整シナリオ」(c)で役立つCountdownEventクラスです。基本的に、すべての並列タスクが終了するまで待つことができます。 チャネル9 での使用例を含むスクリーンキャスト

"Parallel Computing" でタグ付けされた多数のスクリーンキャストとビデオをチャンネル9で見ることができます。

36
Artiom Chilaru

はい、.NET 4は タスク並列ライブラリ を追加しました。これは、高レベルで、以下のサポートを追加します。

  • Parallel.ForおよびParallel.ForEachで並列ループを実行する
  • Parallel.InvokeまたはTaskクラスを使用してタスクを作成または実行します
  • PLINQ(オブジェクトへの並列LINQ)

元の質問への更新に答える...

TPLは、.NET 4を使用して並列タスクを作成するpreferred方法です。スレッドプールアイテムを自分で作成し、同じ「手動」をすべて実行できます。以前にできたスレッド技術。覚えておくべきことは、スレッドプール全体(およびスレッドに関連するほとんどすべて)がTPLを利用するように書き直されているということです。つまり、スレッドプールアイテムを自分で作成した場合でも、それを知らなくても、TPLを使用することになります。もう1つ覚えておくべきことは、TPLがはるかに最適化されており、使用可能なプロセッサの数に基づいてより適切にスケーリングされることです。

それぞれがどのような状況に最も適しているかを知ることに関しては、「特効薬」の答えはありません。以前に独自のスレッドプールアイテムをキューに入れていた(またはマルチスレッドで何かを行っていた)場合は、コードのその部分を変更して、何の影響もなくTPLを使用できます。

並列ループや並列クエリなどの場合は、コードとそのコードの実行を分析して、並列化が適切かどうかを判断する必要があります。

15
Scott Dorman

厳密に言えば、これはC#4.0であり、新しいクラスではありませんが、イベント よりスマートな形式のロックが可能になりました 変更を正しく理解した場合、removes以下に示すようなロックコードのreemの必要性( この記事 JonSkeetによる):

SomeEventHandler someEvent;
readonly object someEventLock = new object();

public event SomeEventHandler SomeEvent
{
    add
    {
        lock (someEventLock)
        {
            someEvent += value;
        }
    }
    remove
    {
        lock (someEventLock)
        {
            someEvent -= value;
        }
    }
}
1
Chris S