C# 在iSyncEnumerable中屈服的替代方案

C# 在iSyncEnumerable中屈服的替代方案,c#,asynchronous,ienumerable,c#-8.0,iasyncenumerable,C#,Asynchronous,Ienumerable,C# 8.0,Iasyncenumerable,我试图检索使用C#8.0中新的AsyncEnumerable分页的数据。在同步IEnumerable世界中,代码看起来是这样的: private IEnumerable<S3Object> Example(S3FilesRequest requestData) { var request = new ListObjectsV2Request() { BucketName = requestData.Bucket,

我试图检索使用C#8.0中新的AsyncEnumerable分页的数据。在同步IEnumerable世界中,代码看起来是这样的:

private IEnumerable<S3Object> Example(S3FilesRequest requestData)
    {
        var request = new ListObjectsV2Request()
        {
            BucketName = requestData.Bucket,
            Prefix = requestData.KeyPrefix
        };

        ListObjectsV2Response response;
        do
        {
            response = this.client.ListObjectsV2Async(request).Result;
            foreach (var s3Obj in response.S3Objects)
                yield return s3Obj;
            request.ContinuationToken = response.NextContinuationToken;
        } while (response.IsTruncated);
    }
    // Not tested - can probably be more succinct (using TakeWhile and SelectMany) but you get the idea
private IAsyncEnumerable<S3Object> listObjects(S3FilesRequest requestData)
        => AsyncEnumerable.CreateEnumerable(() =>
        {
            var request = new ListObjectsV2Request()
            {
                BucketName = requestData.Bucket,
                Prefix = requestData.KeyPrefix
            };
            ListObjectsV2Response response = null;
            List<S3Object>.Enumerator enumerator = default;
            S3Object current = null;
            bool movedNext = false;

            return AsyncEnumerable.CreateEnumerator<S3Object>(async c =>
            {
                if (response == null || !movedNext)
                {
                    enumerator.Dispose();
                    response = await this.client.ListObjectsV2Async(request, c);
                    enumerator = response.S3Objects.GetEnumerator();
                }

                movedNext = enumerator.MoveNext();
                current = enumerator.Current;

                request.ContinuationToken = response.NextContinuationToken;
                return movedNext || response.IsTruncated;
            }, () => current, enumerator.Dispose);
        });
如果您使用的是C#8.0,那么您可以将
yield
async
配合使用:

private async IAsyncEnumerable<S3Object> Example(S3FilesRequest requestData)
{
  var request = new ListObjectsV2Request()
  {
    BucketName = requestData.Bucket,
    Prefix = requestData.KeyPrefix
  };

  ListObjectsV2Response response;
  do
  {
    response = await this.client.ListObjectsV2Async(request);
    foreach (var s3Obj in response.S3Objects)
      yield return s3Obj;
    request.ContinuationToken = response.NextContinuationToken;
  } while (response.IsTruncated);
}
专用异步IAsyncEnumerable示例(S3FileRequestData)
{
var request=new ListObjectsV2Request()
{
BucketName=requestData.Bucket,
Prefix=requestData.KeyPrefix
};
ListObjectsV2响应响应;
做
{
response=等待this.client.ListObjectsV2Async(请求);
foreach(响应中的var s3Obj.S3Objects)
收益率;
request.ContinuationToken=response.NextContinuationToken;
}while(response.IsTruncated);
}

(异步LINQ方法,如
TakeWhile
SelectMany
在中)

谢谢Stephen,该软件包将非常有用。然而,上面的代码基本上是我最初编写的。如果我尝试使用它,尽管我在VS中没有任何红色下划线,但我会得到很多生成错误,如:
CS0656缺少编译器所需的成员系统。Threading.Tasks.ValueTask1..ctor'
CS0518预定义类型“System.Runtime.CompilerServices.asynciiteratormethodbuilder”没有定义或导入,这让我想到我可能在升级到C#8的过程中破坏了我的项目,或者我丢失了一些核心软件包,我将进一步调查。解决了这个问题,当我使用IAsyncEnumerable ReSharper提供的升级语言版本时,它还静默地安装了软件包System.Interactive.Async。我已经卸载并安装了System.Linq.Async,现在一切正常。谢谢你的帮助。顺便问一下,为什么这个问题被否决了?
private async IAsyncEnumerable<S3Object> Example(S3FilesRequest requestData)
{
  var request = new ListObjectsV2Request()
  {
    BucketName = requestData.Bucket,
    Prefix = requestData.KeyPrefix
  };

  ListObjectsV2Response response;
  do
  {
    response = await this.client.ListObjectsV2Async(request);
    foreach (var s3Obj in response.S3Objects)
      yield return s3Obj;
    request.ContinuationToken = response.NextContinuationToken;
  } while (response.IsTruncated);
}