multithreading - 如何在 ASP.NET CORE 上将同步结构转换为异步
问题描述
我有一个类的树层来从数据库中获取数据并在一个动作中提供它。SqlParameter
我使用类从数据库旧方式获取数据。
我需要/想要将此方法重构为异步方法。我真正想要的是学习如何将这些同步方法变为异步。并让它们在不同的线程中工作,并在整个应用程序中使用它们。
我不想做的是使用 Ado.Net 或使用现成的方法,如HttpClient.GetAsync
我读到了这个问题:Calling async methods from non-async code but could not apply to my structure and cannot be sure it is working normal, Avoids deadlocks。
我的旧结构是这样的:
我在我的行动BlockController
:
public ActionResult Index()
{
return View(new BlockDb().Select());
}
课堂上的Select
方法BlockDb
:
public List<Block> Select()
{
SqlDataReader dr = DbJobs.ExecuteReader("BlockSelect");
List<Block> list = new List<Block>();
Block cs;
while (dr.Read())
{
cs = new Block();
cs.ID = Convert.ToInt32(dr["ID"]);
cs.Name= Convert.ToString(dr["Name"]);
cs.Dt = Convert.ToDateTime(dr["Dt"]);
cs.Ok = Convert.ToBoolean(dr["Ok"]);
list.Add(cs);
}
dr.Close();
dr.Dispose();
return list;
}
静态类中的最后一个ExecuteReader
方法:DbJobs
public static SqlDataReader ExecuteReader(string ProcName, params SqlParameter[] prmtr)
{
SqlDataReader Result = null;
SqlConnection connect = new SqlConnection(cnn);
try
{
SqlCommand command = new SqlCommand(ProcName, connect);
command.CommandType = CommandType.StoredProcedure;
foreach (SqlParameter item in prmtr)
command.Parameters.Add(item);
if (connect.State == ConnectionState.Closed)
connect.Open();
Result = command.ExecuteReader(CommandBehavior.CloseConnection);
//connect.Close();
//connect.Dispose();
}
catch { }
return Result;
}
我不能确定一个动作的结果可能是这样的:
public async Task<ActionResult> Index()
{
return View(await new BlockDb().SelectAsync());
}
我怎样才能做到这一点?
解决方案
要将代码转换为异步,最好从最低级别开始,然后逐步向上。因此,从 开始DbJobs
,将每个方法更改为其异步等效方法和await
结果:
public static SqlDataReader ExecuteReader(string ProcName, params SqlParameter[] prmtr)
{
SqlDataReader Result = null;
SqlConnection connect = new SqlConnection(cnn);
try
{
SqlCommand command = new SqlCommand(ProcName, connect);
command.CommandType = CommandType.StoredProcedure;
foreach (SqlParameter item in prmtr)
command.Parameters.Add(item);
if (connect.State == ConnectionState.Closed)
await connect.OpenAsync(CancellationToken.None);
Result = await command.ExecuteReaderAsync(CommandBehavior.CloseConnection);
}
catch { }
return Result;
}
这会给你一个编译器错误,告诉你改变你的DbJobs.ExecuteReader
签名。所以,如果你按照编译器错误告诉你的去做,你最终会得到:
public static async Task<SqlDataReader> ExecuteReaderAsync(string ProcName, params SqlParameter[] prmtr)
现在,您将得到所有调用 . 的旧代码的编译器错误DbJobs.ExecuteReader
,例如BlockDb.Select
. 因此,也将它们更改为使用异步方法:
public List<Block> Select()
{
SqlDataReader dr = await DbJobs.ExecuteReaderAsync("BlockSelect");
List<Block> list = new List<Block>();
Block cs;
while (await dr.ReadAsync(CancellationToken.None))
{
cs = new Block();
cs.ID = Convert.ToInt32(dr["ID"]);
cs.Name= Convert.ToString(dr["Name"]);
cs.Dt = Convert.ToDateTime(dr["Dt"]);
cs.Ok = Convert.ToBoolean(dr["Ok"]);
list.Add(cs);
}
dr.Close();
dr.Dispose();
return list;
}
同样,您将收到一个编译器错误,告诉您如何更改BlockDb.Select
:
public async Task<List<Block>> SelectAsync()
最后,您将对Index
:
public async Task<ActionResult> Index()
{
return View(await new BlockDb().SelectAsync());
}
推荐阅读
- monaco-editor - 在光标位置访问类型定义?
- c# - 如何使用键作为内部列表中的项目初始化字典?
- python - 我有一些事件的实例和该事件的票证实例如何将所有创建的票证实例添加到事件实例列表
- gatsby - 使用 createPage 将组件传递到页面上下文
- terraform - terraform 执行计划中的前缀有什么区别?
- javascript - Javascript else if 语句意外停止执行
- azure - 在 Azure 数据工厂中保存触发器参数以更新插入最近修改的行
- tensorflow2.0 - 在 windows 10 中安装 tensorflow 后出现此错误
- c++ - 在 C++ 运行时删除数组以节省一些内存
- node.js - “TypeError:无法读取未定义的属性'objectMode'”在firebase管理存储中调用bucket.upload时