如何使用DataReader的Task Parallel库

Tho*_*mas 5 c# task-parallel-library

我经常用数据填充数据阅读器并以这种方式填充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
}
Run Code Online (Sandbox Code Playgroud)

我正在寻找使用DataReader的任务并行库并找到一段代码.它看起来不错,但对我来说目标不是很明确.所以这是我得到的代码.

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 ...);
        }
    }
}
}
Run Code Online (Sandbox Code Playgroud)

打电话给

Parallel.ForEach(this.ReadData(), data =>
{
// Use the data here...
});
Run Code Online (Sandbox Code Playgroud)

要么

this.ReadData().AsParallel().ForAll(data => 
{
// Use the data here...
});
Run Code Online (Sandbox Code Playgroud)

我怎样才能从ForAll获取数据.

谁能帮助我理解的代码片段,它是如何工作以及如何获取数据的ForAll我怎么能填充从我的UI 的ForAll.

另一个问题是我怎么知道哪个类是线程安全的.什么是线程安全的意思.一个人说datareader不是线程安全的.他怎么知道的.

一个人应该使用任务并行库的另一个问题.请指导.谢谢

Ste*_*ven 15

您可以在MSDN文档中找到有关.NET基类库中每种类型的线程安全性的信息.大多数类型是不是线程安全的.SqlDataReader例如,它不是线程安全的,因为它适用于与数据库的单个连接.

然而,Parallel.ForEach是一个非常清晰的结构.你不能真正IEnumerable同时迭代一个多线程,而Parallel.ForEach不是那样做.虽然它会旋转多个线程并且那些多个线程会对给定的线程进行迭代IEnumerable,但Parallel.ForEach确保当时只有一个线程迭代可枚举的线程IEnumerator.它假设处理元素比从枚举中获取项目花费更多时间.迭代可枚举是一个顺序操作.

这意味着即使底层数据源和使用SqlReader它不是线程安全的,您仍然可以使用Parallel.ForEach.并行处理项目.不幸的是,MSDN文档对此并不十分明确,但必须如此,因为IEnumeratorGetEnumerator()方法返回的实例永远不是线程安全的.

当然,你必须确保给定的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);
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 每种类型的MSDN文档都说明它是否是线程安全的.如果没有明确说明,它通常不是线程安全的.线程安全意味着可以从多个线程同时使用类型的实例,而不会有该实例(或整个系统)的状态被破坏的可能性. (3认同)