简体   繁体   English

如何使用DataReader的Task Parallel库

[英]How to work with Task Parallel library with DataReader

i often populate data reader with data and populate UI like this way 我经常用数据填充数据阅读器并以这种方式填充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
}

i was searching for the use of Task Parallel library with DataReader and found piece of code. 我正在寻找使用DataReader的任务并行库并找到一段代码。 it looks nice but objective is not very clear to me. 它看起来不错,但对我来说目标不是很明确。 so here is the code i got. 所以这是我得到的代码。

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 ...);
        }
    }
}
}

calling like 打电话给

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

OR 要么

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

how could i get the data from ForAll . 我怎样才能从ForAll获取数据。

can anyone help me to understand the code snippet that how it works and how to get data from ForAll and how can i populate my UI from ForAll . 谁能帮助我理解的代码片段,我如何工作的,以及如何从获得的ForAll数据和如何填充从我的ForAll UI。

another question that how do i know that which class is thread safe or not. 另一个问题是我怎么知道哪个类是线程安全的。 what does it mean thread safe. 什么是线程安全的意思。 a person said datareader is not thread safe. 一个人说datareader不是线程安全的。 how he knows. 他怎么知道的。

another question when one should use task parallel library. 一个人应该使用任务并行库的另一个问题。 please guide. 请指导。 thanks 谢谢

You can find information about thread-safety of every type in the .NET base class library in the MSDN documentation. 您可以在MSDN文档中找到有关.NET基类库中每种类型的线程安全性的信息。 Most types are not thread-safe. 大多数类型不是线程安全的。 SqlDataReader for instance, is not thread-safe, since it works on a single connection to the database. 例如, SqlDataReader 不是线程安全的,因为它适用于与数据库的单个连接。

However, Parallel.ForEach is a very clearer construct. 但是, Parallel.ForEach是一个非常清晰的构造。 You can't really iterate an IEnumerable with multiple thread simultaneously, and Parallel.ForEach doesn't do that. 你不能真正迭代同时使用多个线程的IEnumerable ,而Parallel.ForEach不会这样做。 Although it spins up multiple threads and those multiple threads do iterate on the given IEnumerable , Parallel.ForEach ensures that only one thread at the time iterates the enumerable's IEnumerator . 虽然它会旋转多个线程并且那些多个线程会在给定的IEnumerable上进行迭代,但Parallel.ForEach确保当时只有一个线程迭代可枚举的IEnumerator It operates on the assumption that processing elements takes more time than getting the items from the enumerable. 它假设处理元素比从枚举中获取项目花费更多时间。 Iterating the enumerable is a sequential operation. 迭代可枚举是一个顺序操作。

This means that even if the underlying data source and the use of the SqlReader is not thread-safe, you can still process the items in parallel using the Parallel.ForEach . 这意味着即使底层数据源和SqlReader的使用不是线程安全的,您仍然可以使用Parallel.ForEach处理项目。 Unfortunately, the MSDN documentation isn't very explicit about this, but it has to be, since IEnumerator instances returned from GetEnumerator() methods are never thread-safe. 遗憾的是,MSDN文档对此并不十分明确,但必须如此,因为从GetEnumerator()方法返回的IEnumerator实例从不是线程安全的。

Still you have to make sure that the given Action<T> is thread-safe, of course. 当然,你必须确保给定的Action<T>是线程安全的。

You can see this behavior, using the following program: 您可以使用以下程序查看此行为:

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);
    });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM