C# 并行执行存储过程
我有这两种方法C# 并行执行存储过程,c#,asp.net-mvc,task-parallel-library,C#,Asp.net Mvc,Task Parallel Library,我有这两种方法 public DataTable GetData1(int Id) { DataTable dt = new DataTable(); using (SqlConnection sqlcon = new SqlConnection(database.Connection.ConnectionString)) { using (SqlCommand cmd = new SqlCommand("spGetData1", sqlcon))
public DataTable GetData1(int Id)
{
DataTable dt = new DataTable();
using (SqlConnection sqlcon = new SqlConnection(database.Connection.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("spGetData1", sqlcon))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter() { ParameterName = "@id", Value = Id});
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
}
}
return dt;
}
public DataTable GetData2(int Id)
{
DataTable dt = new DataTable();
using (SqlConnection sqlcon = new SqlConnection(database.Connection.ConnectionString))
{
using (SqlCommand cmd = new SqlCommand("spGetData2", sqlcon))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter() { ParameterName = "@id", Value = Id});
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
}
}
return dt;
}
我想立即执行它们,并获取数据进行进一步处理
我试过类似的东西
var task1 = Task.Factory.StartNew(() => database.Data.GetData1(1));
var task2 = Task.Factory.StartNew(() => database.Data.GetData2(2));
var taskList = new List<Task> { task1, task2 };
Task.WaitAll(taskList.ToArray());
但是错误是一样的,即使我手动设置连接字符串,所以我不认为错误在这里
using (SqlConnection sqlcon = new SqlConnection("connection string ..."))
{
using (SqlCommand cmd = new SqlCommand("spGetData2", sqlcon))
{
...
}
}
我该怎么做?我看到一些示例使用了Async
返回类型,但我不想重复这些方法。更新:
Task.WaitAll
导致当前线程阻塞,直到所有操作都完成。使用Task.whalll
,以免在等待任务完成时占用其他线程
var task1 = Task.Factory.StartNew(() => database.Data.GetData1(1));
var task2 = Task.Factory.StartNew(() => database.Data.GetData2(2));
var taskList = new List<Task> { task1, task2 };
await Task.WhenAll(taskList.ToArray());
var result1 = await task1;
var result2 = await task2;
数据库.Connection.ConnectionString
是一个静态字符串,否则由于“非静态字段、方法或属性需要对象引用”而无法编译
记住这一点,它不是未插入的连接字符串,因为它是静态的。。。即使您有意将静态字符串初始化为Null,错误消息也会是:
InnerException={“ConnectionString属性尚未初始化。”}
这是一个复制,除非GetData方法位于空对象中,否则无法生成错误:
namespace database
{
public class Program
{
static void Main(string[] args)
{
//WORKS!!
var repro = new database.Data();
var task1 = Task.Factory.StartNew(() => repro.GetData1(3));
var task2 = Task.Factory.StartNew(() => repro.GetData2(5));
var taskList = new List<Task> { task1, task2 };
Task.WaitAll(taskList.ToArray());
//FAILS WITH ERROR REPORTED!!
repro = null;
var task1 = Task.Factory.StartNew(() => repro.GetData1(3));
var task2 = Task.Factory.StartNew(() => repro.GetData2(5));
var taskList = new List<Task> { task1, task2 };
Task.WaitAll(taskList.ToArray());
}
}
class Data
{
private string connectionString = "Server=.;Database=CRUD_Sample;Integrated Security=True;Asynchronous Processing = True;";
public DataTable GetData1(int Id)
{
DataTable dt = new DataTable();
using (SqlConnection sqlcon = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand("Get_CustomerbyID", sqlcon))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter() { ParameterName = "@id", Value = Id });
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
}
}
return dt;
}
public DataTable GetData2(int Id)
{
DataTable dt = new DataTable();
using (SqlConnection sqlcon = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand("Get_CustomerbyID", sqlcon))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter() { ParameterName = "@id", Value = Id });
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
}
}
return dt;
}
}
}
名称空间数据库
{
公共课程
{
静态void Main(字符串[]参数)
{
//工作!!
var repro=new database.Data();
var task1=Task.Factory.StartNew(()=>repo.GetData1(3));
var task2=Task.Factory.StartNew(()=>repo.GetData2(5));
var taskList=新列表{task1,task2};
Task.WaitAll(taskList.ToArray());
//失败并报告错误!!
repo=null;
var task1=Task.Factory.StartNew(()=>repo.GetData1(3));
var task2=Task.Factory.StartNew(()=>repo.GetData2(5));
var taskList=新列表{task1,task2};
Task.WaitAll(taskList.ToArray());
}
}
类数据
{
private string connectionString=“Server=;Database=CRUD_Sample;Integrated Security=True;异步处理=True;”;
公共数据表GetData1(int Id)
{
DataTable dt=新的DataTable();
使用(SqlConnection sqlcon=newsqlconnection(connectionString))
{
使用(SqlCommand cmd=newsqlcommand(“Get_customerbyd”,sqlcon))
{
cmd.CommandType=CommandType.storedProcess;
cmd.Parameters.Add(新的SqlParameter(){ParameterName=“@id”,Value=id});
使用(SqlDataAdapter da=newsqldataadapter(cmd))
{
da.填充(dt);
}
}
}
返回dt;
}
公共数据表GetData2(int Id)
{
DataTable dt=新的DataTable();
使用(SqlConnection sqlcon=newsqlconnection(connectionString))
{
使用(SqlCommand cmd=newsqlcommand(“Get_customerbyd”,sqlcon))
{
cmd.CommandType=CommandType.storedProcess;
cmd.Parameters.Add(新的SqlParameter(){ParameterName=“@id”,Value=id});
使用(SqlDataAdapter da=newsqldataadapter(cmd))
{
da.填充(dt);
}
}
}
返回dt;
}
}
}
调试
如何找到NullReferenceException的源?除了查看异常本身,关键是NRE将准确地抛出在发生异常的位置,然后将鼠标悬停在代码行上的变量上,查看哪个对象为空。您应该调查
内部异常
,以了解您得到的异常,因为它是一个没有实际错误的包装器aggregateeexception
information@Cameron,他使用的是自动打开连接的SqlDataAdapter
。堆栈跟踪是什么?@Muflix我只看到一个可能的候选者:数据库。连接
很难回答,因为只有数据库(或database.Connection,若数据库已被释放)在这里可以为null,并且您完全并没有显示任何关于“数据库”的内容变量。显示完整的类定义谢谢你的回答,我试过了,但错误是一样的,我用这个场景更新了我的问题。@Muflix如果你用而不是全部等待,会有什么不同吗?我相信这是问题的根源。全部等待会导致其他线程阻塞。我将代码改为>Task.WhenAll(taskList.ToArray());
它不会抛出任何错误,但在数据库探查器中我没有看到任何数据库命中。当我将代码更改为等待Task.WhenAll(taskList.ToArray())ActhCalm只能在异步方法中使用。请考虑用AsiNC修饰符标记该方法,并将其返回类型改为任务< /Cord>。因为我的存储过程不返回<代码>任务< /Cord>对象。@ MUFLIX显示了封装消息中OP.代码的代码。这是一种混合异步和同步代码的情况。谢谢,这在单独的控制台项目中对我有效,但我无法将此解决方案复制到我正在处理的项目中。但是我还没有看到任何差异:/i我尝试再次初始化repristoryDataRepository data=newdatarepository(新的System.Data.Entity.DbContext(@“连接字符串”).Database);
并运行Data.GetData1(1)
但它在Task.WaitAll(taskList.ToArray())中崩溃
行..如果我在没有执行任务的情况下执行它
阻止它工作。@Muflix,你试过Jeremy的调试建议吗?结果如何?哪个对象为空?在GetData()
方法中放置断点,当任务.WaitAll(taskList.ToArray())时,代码控件(黄色调试行)将停止
call激发/执行。然后逐步执行每个方法(在Debug>Threads窗口中冻结一个线程以便于调试),然后您将能够看到database.Data<
public class MyDataClass {
string connectionString;
private Database database;
public MyDataClass(DbContext context) {
this.database = context.Database;
connectionString = database.Connection.ConnectionString;
}
public DataTable GetData1(int Id) {
var dt = new DataTable();
using (var sqlcon = new SqlConnection(connectionString)) {
using (var cmd = new SqlCommand("spGetData1", sqlcon)) {
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter() { ParameterName = "@id", Value = Id });
using (var da = new SqlDataAdapter(cmd)) {
da.Fill(dt);
}
}
}
return dt;
}
public DataTable GetData2(int Id) {
var dt = new DataTable();
using (var sqlcon = new SqlConnection(connectionString)) {
using (var cmd = new SqlCommand("spGetData2", sqlcon)) {
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter() { ParameterName = "@id", Value = Id });
using (var da = new SqlDataAdapter(cmd)) {
da.Fill(dt);
}
}
}
return dt;
}
}
namespace database
{
public class Program
{
static void Main(string[] args)
{
//WORKS!!
var repro = new database.Data();
var task1 = Task.Factory.StartNew(() => repro.GetData1(3));
var task2 = Task.Factory.StartNew(() => repro.GetData2(5));
var taskList = new List<Task> { task1, task2 };
Task.WaitAll(taskList.ToArray());
//FAILS WITH ERROR REPORTED!!
repro = null;
var task1 = Task.Factory.StartNew(() => repro.GetData1(3));
var task2 = Task.Factory.StartNew(() => repro.GetData2(5));
var taskList = new List<Task> { task1, task2 };
Task.WaitAll(taskList.ToArray());
}
}
class Data
{
private string connectionString = "Server=.;Database=CRUD_Sample;Integrated Security=True;Asynchronous Processing = True;";
public DataTable GetData1(int Id)
{
DataTable dt = new DataTable();
using (SqlConnection sqlcon = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand("Get_CustomerbyID", sqlcon))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter() { ParameterName = "@id", Value = Id });
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
}
}
return dt;
}
public DataTable GetData2(int Id)
{
DataTable dt = new DataTable();
using (SqlConnection sqlcon = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand("Get_CustomerbyID", sqlcon))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter() { ParameterName = "@id", Value = Id });
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
}
}
return dt;
}
}
}