6

私はよくデータリーダーにデータを入力し、このようにUIに入力します

using (SqlConnection conn = new SqlConnection("myConnString"))
using (SqlCommand comm = new SqlCommand("Select * from employee where salary<5000", conn))
{
    conn.Open();

    SqlDataReader reader = comm.ExecuteReader();

    if (reader.HasRows)
    {
        while (reader.Read())
        {
            // here i populate my employee class
        }
    }
    // here i update UI
}

私は DataReader で Task Parallel ライブラリの使用を探していて、コードの一部を見つけました。それは良さそうに見えますが、目的は私にはあまり明確ではありません。ここに私が得たコードがあります。

public IEnumerable<MyDataClass> ReadData()
{
using (SqlConnection conn = new SqlConnection("myConnString"))
using (SqlCommand comm = new SqlCommand("myQuery", conn))
{
    conn.Open();

    SqlDataReader reader = comm.ExecuteReader();

    if (reader.HasRows)
    {
        while (reader.Read())
        {
            yield return new MyDataClass(... data from reader ...);
        }
    }
}
}

のように呼ぶ

Parallel.ForEach(this.ReadData(), data =>
{
// Use the data here...
});

また

this.ReadData().AsParallel().ForAll(data => 
{
// Use the data here...
});

ForAllからデータを取得するにはどうすればよいですか。

コードスニペットがどのように機能し、 ForAll からデータを取得する方法、および ForAllからUI を作成する方法を理解するのを手伝ってくれる人はいますか?

どのクラスがスレッドセーフかどうかをどのように知ることができるかという別の質問。スレッドセーフとはどういう意味ですか。ある人は、datareader はスレッドセーフではないと言いました。彼がどのように知っているか。

タスク並列ライブラリを使用する必要がある場合の別の質問。ガイドしてください。ありがとう

4

1 に答える 1

19

MSDN ドキュメントの .NET 基本クラス ライブラリのすべての型のスレッド セーフに関する情報を見つけることができます。ほとんどの型はスレッドセーフではありません。SqlDataReaderたとえば、データベースへの単一の接続で動作するため、スレッドセーフではありません。

ただし、Parallel.ForEach非常に明確な構造です。IEnumerable複数のスレッドで同時に反復することは実際にはできず、Parallel.ForEachそうしません。複数のスレッドをスピンアップし、それらの複数のスレッドが指定された を反復しますが、一度に1 つのスレッドのみが列挙可能な を反復することIEnumerableParallel.ForEach保証します。要素の処理には、列挙型からアイテムを取得するよりも時間がかかるという前提で動作します。列挙型の反復は、順次操作です。IEnumerator

これは、基になるデータ ソースと の使用がSqlReaderスレッド セーフでない場合でも、 を使用して項目を並行して処理できることを意味しますParallel.ForEach。残念ながら、MSDN のドキュメントではこれについてあまり明示されていませんが、メソッドIEnumeratorから返されるインスタンスGetEnumerator()は決してスレッド セーフではないため、明示する必要があります。

もちろん、与えられたAction<T>ものがスレッドセーフであることを確認する必要があります。

次のプログラムを使用して、この動作を確認できます。

public static IEnumerable<int> GetNumbers()
{
    for (int i = 0; i < 140; i++)
    {
        Console.WriteLine(
            "                          Enumerating " + 
            i + " at thread " +
            Thread.CurrentThread.ManagedThreadId);

        yield return i;
    }
}

static void Main(string[] args)
{
    Console.ReadLine();

    Parallel.ForEach(GetNumbers(), number =>
    {
        Console.WriteLine("Processing " + number + 
            " at thread " +
            Thread.CurrentThread.ManagedThreadId);

        Thread.Sleep(1);
    });
}
于 2012-08-14T09:52:10.873 に答える