2

我正在尝试为IAsyncEnumerable<T>集合创建一个自定义 DataReader,以便通过SqlBulkCopy. 我正在按照这个问题中概述的代码示例和解决方案的行 -如何使用 SqlBulkCopy 编写 IAsyncEnumerable

这是我的 DataReader 的要点:

internal sealed class AsyncEnumerableDataReader<T> : IDataReader
    {
        private readonly IAsyncEnumerator<T> _asyncEnumerator;
        private readonly List<PropertyInfo> _properties = new List<PropertyInfo>();
        private bool _isClosed = false;

        public AsyncEnumerableDataReader(IAsyncEnumerable<T> asyncEnumerable)
        {
            _asyncEnumerator = asyncEnumerable.GetAsyncEnumerator();

            foreach (PropertyInfo propertyInfo in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                _properties.Add(propertyInfo);
            }
        }

 //.... Other method implementations here

public bool Read() => _asyncEnumerator.MoveNextAsync().Result;
}

我的问题是,当我将 datareader 传递给SqlBulkCopy.WriteToServerAsync(reader)方法时,在第一次调用DataReader.Read()它时会引发以下错误:

System.InvalidOperationException: 'Operation is not valid due to the current state of the object.'

有谁知道我的代码哪里出错了?

4

1 回答 1

2

当您.Result与 a 一起使用时,ValueTask<T>不会阻止当前线程等待结果(bool在您的情况下)。

如果 aValueTask<T>在第一次调用期间没有及时完成,它将返回 a Task,CLR 稍后将使用它继续工作以检查它。

当您不调用时,CLR稍后无法检查结果。await

由于您想同步运行此代码(至少从我可以使用的假设来看),我已经包含了一个应该为您同步.Result工作的解决方法。

考虑使用.AsTask().Result而不是.Result. 这将强制 CLR 在返回结果之前等待任务完成。

public bool Read() => _asyncEnumerator.MoveNextAsync().AsTask().Result;
于 2021-06-10T13:24:00.990 回答