如何在异步数据库连接期间避免 "Access Violation"?
How do I avoid "Access Violation" during asynchronous database connections?
目标:正确使用 ExecuteAsync。
我知道我的应用程序本身至少非常接近更正,因为它正确执行一次,所以我知道我可以消除防火墙的常见嫌疑,错误的数据库密码,程序名称等
private async Task<T> executeAsyncHelper<T>(Func<IDataReader, T> then)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(name, conn))
{
parameters.Select(p => cmd.Parameters.Add(p))
.ToImmutableList();
cmd.CommandType = CommandType.StoredProcedure;
using (IDataReader rdr = await cmd.ExecuteReaderAsync())
{
return then(rdr);
}
}
}
}
问题:第二个 SqlConnection.Open()
上的访问冲突
该方法在同一过程中被调用两次。第一次,它成功地更新了数据库。第二次,整个事情在 conn.Open()
上转储 "Access violation." 重要的是,它没有抛出异常。相反,整个调试器以否定状态代码退出。
这些是调试器输出的最后两行(调试器输出的其余部分看起来很正常):
The program '[6904] dotnet.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'.
The program '[6904] dotnet.exe: Program Trace' has exited with code 0 (0x0).
此行为是 100% 可重复的。
假设:连接池和异步性
据我所知,最可能的原因是异步打开两个连接存在一些问题,但我不立即知道如何做 .我已经尽可能安全地编写了该方法。
其次,我检查了我的 Azure SQL 服务器实例是否有任何异常限制。这是一个基本实例,但我怀疑这是问题所在,因为如果那是问题所在,我希望出现 SQL 异常(调试器将中断并显示正常的堆栈跟踪)。
环境信息
- 蔚蓝 SQL 服务器 2016
- Windows 10
- .NET 核心 2.1
- Visual Studio 2017
结论
有没有人发现我实施此方法的方式有任何问题,或者有任何建议来了解有关该错误的更多信息?
试试这个:
private async Task<T> executeAsyncHelper<T>(Func<IDataReader, Task<T>> then)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(name, conn))
{
parameters.Select(p => cmd.Parameters.Add(p))
.ToImmutableList();
cmd.CommandType = CommandType.StoredProcedure;
using (IDataReader rdr = await cmd.ExecuteReaderAsync())
{
return await then(rdr);
}
}
}
}
注意签名的更改,并等待 return
。
为了检查您是否没有达到连接限制,您可以执行 exec sp_who2 并查看 sql 服务器上有多少连接。如果 sql 服务器上显示很多连接,则可能是资源问题。你有没有在常规同步中尝试 运行 这段代码,它是否导致了同样的问题?您的连接字符串中是否有任何限制连接数的内容?由于我看不到这段代码的上下文,所以只是抛出了一些理论。
非常有信心我想通了。它实际上与程序死亡的精确行没有任何关系。
相反,该程序在其他线程的其他地方溢出了堆栈。 conn.Open()
是一个转移注意力的问题,尽管那是调试器在失败之前总是指向的地方。我的猜测是 conn.Open()
只是资源密集型,足以将其置于边缘,使其看起来像是造成它的原因。
为了将来的参考,如果您 "Access violation," 重构为同步代码,那么调试器将能够直接通过并实际抛出 WhosebugException 而不是崩溃。
目标:正确使用 ExecuteAsync。
我知道我的应用程序本身至少非常接近更正,因为它正确执行一次,所以我知道我可以消除防火墙的常见嫌疑,错误的数据库密码,程序名称等
private async Task<T> executeAsyncHelper<T>(Func<IDataReader, T> then)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(name, conn))
{
parameters.Select(p => cmd.Parameters.Add(p))
.ToImmutableList();
cmd.CommandType = CommandType.StoredProcedure;
using (IDataReader rdr = await cmd.ExecuteReaderAsync())
{
return then(rdr);
}
}
}
}
问题:第二个 SqlConnection.Open()
上的访问冲突该方法在同一过程中被调用两次。第一次,它成功地更新了数据库。第二次,整个事情在 conn.Open()
上转储 "Access violation." 重要的是,它没有抛出异常。相反,整个调试器以否定状态代码退出。
这些是调试器输出的最后两行(调试器输出的其余部分看起来很正常):
The program '[6904] dotnet.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'.
The program '[6904] dotnet.exe: Program Trace' has exited with code 0 (0x0).
此行为是 100% 可重复的。
假设:连接池和异步性
据我所知,最可能的原因是异步打开两个连接存在一些问题,但我不立即知道如何做 .我已经尽可能安全地编写了该方法。
其次,我检查了我的 Azure SQL 服务器实例是否有任何异常限制。这是一个基本实例,但我怀疑这是问题所在,因为如果那是问题所在,我希望出现 SQL 异常(调试器将中断并显示正常的堆栈跟踪)。
环境信息
- 蔚蓝 SQL 服务器 2016
- Windows 10
- .NET 核心 2.1
- Visual Studio 2017
结论
有没有人发现我实施此方法的方式有任何问题,或者有任何建议来了解有关该错误的更多信息?
试试这个:
private async Task<T> executeAsyncHelper<T>(Func<IDataReader, Task<T>> then)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(name, conn))
{
parameters.Select(p => cmd.Parameters.Add(p))
.ToImmutableList();
cmd.CommandType = CommandType.StoredProcedure;
using (IDataReader rdr = await cmd.ExecuteReaderAsync())
{
return await then(rdr);
}
}
}
}
注意签名的更改,并等待 return
。
为了检查您是否没有达到连接限制,您可以执行 exec sp_who2 并查看 sql 服务器上有多少连接。如果 sql 服务器上显示很多连接,则可能是资源问题。你有没有在常规同步中尝试 运行 这段代码,它是否导致了同样的问题?您的连接字符串中是否有任何限制连接数的内容?由于我看不到这段代码的上下文,所以只是抛出了一些理论。
非常有信心我想通了。它实际上与程序死亡的精确行没有任何关系。
相反,该程序在其他线程的其他地方溢出了堆栈。 conn.Open()
是一个转移注意力的问题,尽管那是调试器在失败之前总是指向的地方。我的猜测是 conn.Open()
只是资源密集型,足以将其置于边缘,使其看起来像是造成它的原因。
为了将来的参考,如果您 "Access violation," 重构为同步代码,那么调试器将能够直接通过并实际抛出 WhosebugException 而不是崩溃。