假设我们必须通过异步流程在数据库中写入包含 1000 个元素的列表。是等待 1000 次异步插入语句更好,还是将所有 1000 次插入包装在封装到一个同步方法中?Task.Run
声明,等待一次?
例如,SqlCommand
每种方法都与他的方法相结合async
版本。在本例中,我们有一个插入语句,因此我们可以调用ExecuteNonQuery
or ExecuteNonQueryAsync
.
通常,在异步/等待指南中,我们读到如果您有可用于某些方法的异步版本,则应该使用它。所以假设我们写:
async Task Save(IEnumerable<Savable> savables)
{
foreach(var savable in savables)
{
//create SqlCommand somehow
var sqlCmd = CreateSqlCommand(savable);
//use asynchronous version
await sqlCmd.ExecuteNonQueryAsync();
}
}
这段代码非常清楚。然而,每次它从await部分出去时,它也会在UI线程上返回,然后在遇到的下一个await中返回到后台线程,依此类推(不是吗?)。这意味着用户可能会看到一些延迟,因为 UI 线程会被继续执行的操作不断中断。await
执行下一个foreach
循环,在这段时间里,用户界面有点冻结。
我想知道我是否最好编写这样的代码:
async Task Save(IEnumerable<Savable> savables)
{
await Task.Run(() =>
{
foreach(var savable in savables)
{
//create SqlCommand somehow
var sqlCmd = CreateSqlCommand(savable);
//use synchronous version
sqlCmd.ExecuteNonQuery();
}
});
}
这样一来,整个foreach
在辅助线程上执行,无需在 UI 线程和辅助线程之间不断切换。
这意味着 UI 线程可以在整个持续时间内自由更新视图。foreach
(例如旋转器或进度条),也就是说,用户不会感觉到任何延迟。
我对吗?或者我错过了一些关于“异步一直下来”的事情?
我不是在寻找简单的基于意见的答案,而是在寻找异步/等待准则的解释(以防出现这种情况)以及解决该问题的最佳方法。
EDIT:
我读了这个问题 https://stackoverflow.com/questions/32606485/calling-an-async-method-using-a-task-run-seems-wrong但它不一样。这个问题是关于单身人士的选择await
异步方法与单个方法Task.Run
等待。这个问题是关于拨打1000的后果await
以及由于线程之间不断切换而产生的资源开销。