【问题标题】:How to work with Task Parallel library with DataReader如何使用 DataReader 使用 Task Parallel 库
【发布时间】:2012-08-14 19:11:24
【问题描述】:

我经常用数据填充数据读取器并以这种方式填充 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 获取数据。

谁能帮我理解代码 sn-p 它的工作原理以及如何从 ForAll 获取数据以及如何从 ForAll 填充我的 UI。

另一个问题是我如何知道哪个类是线程安全的。这是什么意思线程安全。有人说数据读取器不是线程安全的。他怎么知道的。

另一个问题何时应该使用任务并行库。 请指导。谢谢

【问题讨论】:

  • 如果您想在没有性能问题的情况下使用 TPL '只是为了使用它',那么我不会打扰。它让你的想法比你现在想象的更复杂。

标签: c# task-parallel-library


【解决方案1】:

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

但是,Parallel.ForEach 是一个非常清晰的结构。您不能真正使用多个线程同时迭代IEnumerable,而Parallel.ForEach 不会这样做。尽管它启动了多个线程并且这些多个线程确实在给定的IEnumerable 上进行迭代,但Parallel.ForEach 确保当时只有一个 线程迭代可枚举的IEnumerator。它假设处理元素比从可枚举项中获取项目花费更多时间。迭代可枚举是一个顺序操作。

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

当然,您仍然必须确保给定的Action&lt;T&gt; 是线程安全的。

您可以使用以下程序查看此行为:

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

【讨论】:

  • 人们常说这个类不是线程安全的,就像datareader不是线程安全的一样。也许他们是对的,但我不知道哪些 dotnet 内置类是线程安全的。所以我想知道人们如何检测到任何特定的类是否是线程安全的,以及他们试图表示线程安全的含义是什么?帮助我知道如何检测类是否是线程安全的。谢谢
  • 每种类型的 MSDN 文档解释了它是否是线程安全的。如果它没有明确声明,它通常不是线程安全的。线程安全意味着一个类型的实例可以在多个线程中同时使用,而不会破坏该实例(或整个系统)的状态。
  • 好像 AsParallel().ForAll 也很安全。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多