Я использую следующий код для чтения данных из БД, в котором я считаю построчно:
public async IAsyncEnumerable<(int id, string body)> GetAllPostsAsync() {
using var postsQuery = _sqlConnection.CreateCommand();
postsQuery.CommandText = "SELECT Id, Body FROM Posts";
postsQuery.CommandType = CommandType.Text;
using var postsReader = await postsQuery.ExecuteReaderAsync(CommandBehavior.SequentialAccess);
while (await postsReader.ReadAsync()) {
var postId = await postsReader.GetFieldValueAsync<int>(0);
var postBody = await postsReader.GetFieldValueAsync<string>(1);
yield return (postId, postBody);
}
}
// In another class...
var postsToClean = _postsStore.GetAllPostsAsync();
_progressReporter.ConfigureTicks(postsCount);
await foreach (var post in postsToClean) {
await CleanupPostAsync(post);
}
Насколько я понимаю,Среда выполнения .net будет неявно вызывать CleanupPostAsync
так же быстро, как строки поступают из БД, но это не соответствует поведению, которое я наблюдаю: когда я запускаю этот код и перехожу по yield return (postId, postBody)
, никакая другая строка не попадает и, в конце концов,Выдается исключение тайм-аута SQL.
Почему это исключение тайм-аута срабатывает, если я получаю строки по одной, а не целый кусок данных таблицы?
Этот вопрос может возникнуть из-за неправильного пониманиятеория асинхронных потоков.
Я выполняю этот код на .Net Core 3-preview5 с C # 8 и VS 2019 Pro, запрашивая контейнер докера для SQL Server Linux 14.0;