【问题标题】:Parallel.Foreach loop creating multiple db connections throws connection errors?Parallel.Foreach 循环创建多个数据库连接会引发连接错误?
【发布时间】:2012-07-07 17:04:05
【问题描述】:

“登录失败”错误从未再次出现,好奇吗?但是,其他连接错误似乎可以通过猛击服务器来解释。错误发生的随机性仍然是个谜。

登录失败。登录来自不受信任的域,不能用于 Windows 身份验证

我想让我的代码并行运行,因此我将 foreach 循环更改为并行 foreach 循环。这似乎很简单。每个循环都连接到数据库,查找一些内容,执行一些逻辑,添加一些内容,关闭连接。但是我得到了上述错误?

我正在使用我的本地 sql 服务器和实体框架(每个循环都使用它自己的上下文)。使用相同的本地登录名连接多次是否有问题?我是如何解决这个问题的?

我(在尝试转换为 parallel.foreach 循环之前)将我正在 foreach 循环的对象列表拆分为四组(单独的 csv 文件)并运行我的程序的四个并发实例(总体运行速度比只有一个,因此是并行的想法)。所以看来连接db应该没问题吧?

有什么想法吗?

编辑: 这是以前的

var gtgGenerator = new CustomGtgGenerator();
var connectionString = ConfigurationManager.ConnectionStrings["BioEntities"].ConnectionString;

var allAccessionsFromObs = _GetAccessionListFromDataFiles(collectionId);

ForEach(cloneIdAndAccessions in allAccessionsFromObs)
    DoWork(gtgGenerator, taxonId, organismId, cloneIdAndAccessions, connectionString));

之后

var gtgGenerator = new CustomGtgGenerator();
var connectionString = ConfigurationManager.ConnectionStrings["BioEntities"].ConnectionString;

var allAccessionsFromObs = _GetAccessionListFromDataFiles(collectionId);

Parallel.ForEach(allAccessionsFromObs, cloneIdAndAccessions => DoWork(gtgGenerator, taxonId, organismId, cloneIdAndAccessions, connectionString));

在 DoWork 中我使用 BioEntities

using (var bioEntities = new BioEntities(connectionString)) {...}

越来越好奇了……

我在 DoWork 方法中添加了一些代码:

Debug.WriteLine(“Executing “ + itemName + ” as “ + WindowsIdentity.GetCurrent().Name);

它神秘地开始工作(实际上很好/很快)。但最终我得到了同样的例外(大约一个小时后)。但我能够追踪到这一点..?

A first chance exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll

EDIT2: 嗯..我今天早上进来工作并把它烧了(痴迷于理解为什么它会工作一点点),到目前为止它工作得很好(而且很快!)。偶尔:线程 '' (0x27c8) 以代码 0 (0x0) 退出。 线程 '' (0x26b8) 已退出,代码为 0 (0x0)。

但除此之外它还没有搞砸吗?坦率地说,这让我更担心。这是一次性的,所以我可以使用它(如果它有效),但发生了什么?会不会是 NLOG,登录多个线程会阻塞东西并导致 sql 超时?我真的不明白。一旦它再次停止工作,我将尝试解决问题。有没有办法重置 sql server,我不知道为什么它会工作一个小时,然后搞砸,然后永远不会工作超过几秒钟,现在(重新启动后)工作(大约 30 分钟迄今为止)?

【问题讨论】:

  • 链接中的建议都没有任何效果。
  • 好的!那么这很奇怪吗?我尝试了所有这些不同的建议,但没有成功。然后我决定从 robseder.wordpress.com 链接中尝试这段代码:Debug.WriteLine("Executing" + cloneIdAndAccessions.Item1.ToString() + " as " + WindowsIdentity.GetCurrent().Name) 我想看看哪些用户名看起来像。你不知道吗?现在才有效?我什至没有身份传递等。我只添加了该代码。奇怪!?
  • 令人沮丧 - 它曾经那么好用吗?现在我又回到了从不超过一分钟的状态?

标签: c# sql entity-framework task-parallel-library


【解决方案1】:

您的身份不会流向执行并行 for.each 的底层任务的工作线程。

这里的答案很好,所以我不会重复它。 TPL Task in WCF service fails to use correct IIS security Credentials (SQL Connection)

【讨论】:

  • IIRC 有一些政策包括链接的相关位,以防目标链接消失(即使对于 SO 问题,AFAICT 也可能发生这种情况)?
  • 嗯,即使是 SO 参考?如果稍后关闭它与我提供的链接完全相同,我不会感到惊讶。
  • 嗯,这两种选择都不起作用,所以我可能不清楚如何让身份流向 Parallel.Foreach 任务,或者完全不同?
  • @KennethIto:您没有回答 SO 上另一个答案的链接。您投票决定以骗子身份关闭或将其添加为评论。
  • @sixletter 变量。著名的。虽然我不能投票结束作为骗子,但我想首选的方式是评论。
【解决方案2】:

好的,很抱歉回答我自己的问题,但它可能对某人、某地、某时有价值。

在添加(并随后删除)以下代码以查看每个线程使用的身份后,“登录失败”错误不再发生。我不确定使用它是否会影响某些东西,但我现在不使用它,而且它似乎从未在最初给出的链接和答案中讨论过身份问题。

Debug.WriteLine("Executing " + cloneIdAndAccessions.Item1.ToString() + " as " + WindowsIdentity.GetCurrent().Name);

这里一定有两个问题,第一个是掩盖后者。 但我仍然收到以下两种类型的连接错误。特别是(我注意到)在打开 SQL Server Management Studio 并可能使服务器紧张之后。

System.Data.EntityCommandExecutionException: An error occurred while reading from the store provider's data reader. See the inner exception for details. ---> System.Data.SqlClient.SqlException: The query processor could not start the necessary thread resources for parallel query execution.

还有……

System.Data.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details. ---> System.Data.SqlClient.SqlException: Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.

所以,我的解决方案(因为我找不到错误何时出现的押韵或理由)是简单地捕获错误并记录 Parallel.ForEach 循环中哪个对象抛出它,然后重新运行这些对象。仍然比简单的 foreach 循环快得多。

编辑:嗯,这很有趣,我发现了错误的一些押韵/原因(不是当它们被抛出时,而是可能是为什么)。如果我将 Parallel.ForEach 循环中的对象数量分成更小的(10,000 个对象而不是 100,000 个)组,那么我永远不会抛出任何异常。不错。

所以总结 - 检查身份,然后可能会分解您在 foreach 循环中运行的组......有人弄清楚为什么这是必要的并报告回来:)

编辑/结束

不是最好的解决方案,但与深入研究任务和线程疯狂相比相对简单。

【讨论】:

    猜你喜欢
    • 2013-05-17
    • 2018-01-09
    • 2016-05-11
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    • 2021-11-27
    • 2019-05-15
    • 1970-01-01
    相关资源
    最近更新 更多