在 IAsyncEnumerable 中产生的替代方法
Alternative to yielding in an IAsyncEnumerable
我正在尝试检索使用 C# 8.0 中的新 AsyncEnumerables 分页的数据。回到同步 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
使用 IAsyncEnumerable 我认为它看起来像这样:
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);
});
这似乎有点啰嗦,但是没有yield关键字有没有更好的方法?
谢谢,
乔
编辑:
这是由 ReSharper 在升级到 C# 8 时静默安装软件包 System.Interactive.Async 引起的。我卸载了它并听从了 Stephen 的建议。
对于Google:
CS0518 Predefined type 'System.Runtime.CompilerServices.AsyncIteratorMethodBuilder' is not defined or imported
CS0656 Missing compiler required member 'System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Create'
CS0656 Missing compiler required member 'System.Collections.Generic.IAsyncEnumerable`1.GetAsyncEnumerator'
CS0656 Missing compiler required member 'System.Collections.Generic.IAsyncEnumerator`1.MoveNextAsync'
CS0656 Missing compiler required member 'System.IAsyncDisposable.DisposeAsync'
CS0656 Missing compiler required member 'System.Threading.Tasks.ValueTask`1..ctor'
CS0656 Missing compiler required member 'System.Threading.Tasks.ValueTask..ctor'
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.GetResult'cs
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.GetStatus'cs
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.get_Version'cs
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.OnCompleted'cs
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.Reset'
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.SetExceptioncs
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.SetResult'cs
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.IValueTaskSource`1.GetResult'
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.IValueTaskSource`1.GetStatus'
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.IValueTaskSource`1.OnCompleted'
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.IValueTaskSource.GetResult'
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.IValueTaskSource.GetStatus'
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.IValueTaskSource.OnCompleted'
如果您使用的是 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);
}
(以及 TakeWhile
和 SelectMany
等异步 LINQ 方法在 System.Linq.Async
package 中)
我正在尝试检索使用 C# 8.0 中的新 AsyncEnumerables 分页的数据。回到同步 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
使用 IAsyncEnumerable 我认为它看起来像这样:
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);
});
这似乎有点啰嗦,但是没有yield关键字有没有更好的方法?
谢谢,
乔
编辑:
这是由 ReSharper 在升级到 C# 8 时静默安装软件包 System.Interactive.Async 引起的。我卸载了它并听从了 Stephen 的建议。
对于Google:
CS0518 Predefined type 'System.Runtime.CompilerServices.AsyncIteratorMethodBuilder' is not defined or imported
CS0656 Missing compiler required member 'System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Create'
CS0656 Missing compiler required member 'System.Collections.Generic.IAsyncEnumerable`1.GetAsyncEnumerator'
CS0656 Missing compiler required member 'System.Collections.Generic.IAsyncEnumerator`1.MoveNextAsync'
CS0656 Missing compiler required member 'System.IAsyncDisposable.DisposeAsync'
CS0656 Missing compiler required member 'System.Threading.Tasks.ValueTask`1..ctor'
CS0656 Missing compiler required member 'System.Threading.Tasks.ValueTask..ctor'
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.GetResult'cs
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.GetStatus'cs
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.get_Version'cs
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.OnCompleted'cs
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.Reset'
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.SetExceptioncs
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore`1.SetResult'cs
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.IValueTaskSource`1.GetResult'
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.IValueTaskSource`1.GetStatus'
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.IValueTaskSource`1.OnCompleted'
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.IValueTaskSource.GetResult'
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.IValueTaskSource.GetStatus'
CS0656 Missing compiler required member 'System.Threading.Tasks.Sources.IValueTaskSource.OnCompleted'
如果您使用的是 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);
}
(以及 TakeWhile
和 SelectMany
等异步 LINQ 方法在 System.Linq.Async
package 中)