【发布时间】:2026-01-09 19:25:01
【问题描述】:
我正在尝试修复的 ASP.NET 应用程序中发生了一些奇怪的行为。
我从代码中收到以下错误:
超时。在操作完成之前超时时间已过或服务器没有响应。
我熟悉此错误及其许多原因。我所有典型的故障排除途径都失败了。
以下是一些动态:
服务器最近重建。所以可能是服务器配置问题。
此错误仅发生在特定的 Web 服务器上。当我在本地运行应用程序时,从其他服务器运行它很快。我无法从我的机器上重新解决 MSSMS 中 proc 的性能问题。
- 这告诉我它是特定于该服务器的。
当我使用 OSql 命令行实用程序运行相同的过程时,它可以工作。快。
- 这表明它可能与 .NET 相关,而不是 db 相关
在执行此代码之前,我已在此服务器和同一数据库上执行了其他存储过程。
- 这表明 proc 可能是相关的,但不是“服务器 X 无法与服务器 Y 通信”
我已经从数据库所有者那里得到确认,数据库已收到命令,执行(>1 秒)它并返回数据。
- 通过跟踪代码,我看到返回了结果,直到我尝试关闭数据读取器才发生错误。
- 事实上,我发现执行存储过程并遍历结果需要 36 毫秒。
看起来对 DataReader.Close 的调用需要时间,最终会超时。
我已将最大池从 31 增加到 100。
这里是我的代码的样例,它的结构是怎样的。我一直在破解它以进行故障排除:我添加了显式关闭以确保我知道错误发生在哪里。可能存在语法问题:我已将其设为通用,并且可能在这样做时引入了错误。
public double GetMyData()
{
double returnValue;
// Used in logging to see if code was reached & how long it took.
System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();
using (SqlConnection cn = Connections.GetSqlConnection())
{
cn.Open();
using (SqlCommand cmd = getSQLCommmand("SomeProcName"))
{
Log.Log.WriteTrace(string.Format("Execute {0} ","SomeProcName"),0);
s.Start();
SqlDataReader dr= null;
try
{
dr = cmd.ExecuteReader();
s.Stop();
Log.Log.WriteTrace("Timer", "ExecuteReader done " + s.ElapsedMilliseconds + "ms ", 0);
s.Start();
if (dr != null)
{
if (dr.Read())
{
returnValue =
Conversion.DBNullToDouble(
dr[0]);
}
s.Stop();
Log.Log.WriteTrace("Timer", "dr.read done (result:" + returnValue + ")" + s.ElapsedMilliseconds + "ms ", 0); // I get Here
}
}catch(Exception ex)
{
Log.Log.PersistException(ex);
}
//}
if(dr!=null && !dr.IsClosed)
dr.Close();// This times out
if (cn != null && cn.State !=ConnectionState.Closed)
cn.Close();
Log.Log.WriteTrace("DONE "),
;
}
}
return (returnValue);
}
更新
dr.Close(); 需要 2 分钟才能执行。就在这台服务器上。在本地只需不到一秒钟。
更新
根据接受的答案的 cmets:我有一个包含多条记录的 proc。我拿的是拳头。调用 cmd.Cancel() 并没有修复,但大大减少了关闭数据读取器所需的时间。探索这一点应该可以帮助我解决问题。我不知道为什么这只发生在这台服务器上,因为服务器是开发服务器。
【问题讨论】:
-
您是否尝试在 using 语句中也使用它?
-
感谢您的评论。我有,原始代码依赖于 Using 语句来管理关闭阅读器和连接。我更改了它,因为错误发生在编译器发出的 IL 中。引发错误的源代码是“}”。我将其转换为显式关闭以确保没有隐藏错误。