How to work with Task Parallel library with DataReader

15,052

You can find information about thread-safety of every type in the .NET base class library in the MSDN documentation. Most types are not thread-safe. SqlDataReader for instance, is not thread-safe, since it works on a single connection to the database.

However, Parallel.ForEach is a very clearer construct. You can't really iterate an IEnumerable with multiple thread simultaneously, and Parallel.ForEach doesn't do that. 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. 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. 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.

Still you have to make sure that the given Action<T> is thread-safe, of course.

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);
    });
}
Share:
15,052
Thomas
Author by

Thomas

i am developer. i am working with .Net technology (v1.1 &amp; v2.0) last 4 year. i like this forum for fast &amp; good response and that is why i joined this forum. my friends profile id Mou :- http://stackoverflow.com/users/728750/user728750?tab=questions and Keith :- http://stackoverflow.com/users/750398/keith-costa thanks

Updated on June 05, 2022

Comments

  • Thomas
    Thomas almost 2 years

    i often populate data reader with data and populate UI like this way

    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. 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.

    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.

    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. how he knows.

    another question when one should use task parallel library. please guide. thanks

    • Maarten
      Maarten over 11 years
      If you are want to use TPL 'just to use it' while you don't have a performance problem, then I wouldn't bother. It makes thinks more complex than you can imagine at the moment.
  • Thomas
    Thomas over 11 years
    people often said that this class is not thread-safe like datareader is not thread-safe. may be they are right but i dont know which dotnet build-in classes are thread-safe or not. so i want to know how people detect that any specific class is thread-safe or not and what they try to mean thread-safe? help me to know how to detect class is thread-safe or not. thanks
  • Steven
    Steven over 11 years
    The MSDN documentation of each type explains if it is thread-safe or not. If it doesn't state explicitly, it usually isn't thread-safe. Thread-safe means that an instance of a type can be used simultaniously from multiple threads, without the chance that the state of that instance (or the whole system) gets corrupt.
  • yatskovsky
    yatskovsky about 8 years
    Seems like AsParallel().ForAll is safe too.