常规迭代器块(即"yield return")是否与"async"和"await"不兼容?
这样可以很好地了解我正在尝试做的事情:
async Task<IEnumerable<Foo>> Method(String [] Strs)
{
// I want to compose the single result to the final result, so I use the SelectMany
var finalResult = UrlStrings.SelectMany(link => //i have an Urlstring Collection
await UrlString.DownLoadHtmlAsync() //download single result; DownLoadHtmlAsync method will Download the url's html code
);
return finalResult;
}
Run Code Online (Sandbox Code Playgroud)
但是,我收到编译器错误,引用"无法从资源加载消息字符串".
这是另一种尝试:
async Task<IEnumerable<Foo>> Method(String [] Strs)
{
foreach(var str in strs)
{
yield return await DoSomethingAsync( str)
}
}
Run Code Online (Sandbox Code Playgroud)
但同样,编译器返回错误:"无法从资源加载消息字符串".
这是我项目中真正的编程代码
当我有一个List Task时,这非常有用,该任务可以从URL下载HTML,我使用语法"yield return await task",结果是我想要的 …
所以在 C#8 中我们添加了IAsyncEnumerable接口。
如果我们有一个法线,IEnumerable我们可以用它制作一个List或几乎任何其他我们想要的集合。感谢那里的 Linq。
var range = Enumerable.Range(0, 100);
var list = range.ToList();
Run Code Online (Sandbox Code Playgroud)
那么现在我想将 my 转换IAsyncEnumerable为 aList并且这当然是异步的。是否已经有针对这种情况的 Linq 实现?如果没有,我怎么能自己转换呢?
我有一个这样写的界面:
public interface IItemRetriever
{
public IAsyncEnumerable<string> GetItemsAsync();
}
Run Code Online (Sandbox Code Playgroud)
我想编写一个不返回任何项目的空实现,如下所示:
public class EmptyItemRetriever : IItemRetriever
{
public IAsyncEnumerable<string> GetItemsAsync()
{
// What do I put here if nothing is to be done?
}
}
Run Code Online (Sandbox Code Playgroud)
如果它是一个普通的 IEnumerable,我会return Enumerable.Empty<string>();,但我没有找到任何AsyncEnumerable.Empty<string>().
我发现这有效但很奇怪:
public async IAsyncEnumerable<string> GetItemsAsync()
{
await Task.CompletedTask;
yield break;
}
Run Code Online (Sandbox Code Playgroud)
任何的想法?
我想对一个调用另一个服务方法的方法进行单元测试,该方法返回一个IAsyncEnumerable<T>. 我已经创建了我的服务的模拟,我Mock<MyService>想设置这个模拟,但我不知道该怎么做。是否可以 ?是否有其他方法可以对调用重新调整的方法进行单元测试IAsyncEnumerable
public async Task<List<String>> MyMethodIWantToTest()
{
var results = new List<string>();
await foreach(var item in _myService.CallSomethingReturningAsyncStream())
{
results.Add(item);
}
return results;
}
Run Code Online (Sandbox Code Playgroud) 我一直在使用 Blazor 和 C# 8.0 中的 IAsyncEnumerable 功能。是否可以在 Razor Pages 中使用 IAsyncEnumerable 和 await 来逐步显示带有数据的标记?
示例服务:
private static readonly string[] games = new[] { "Call of Duty", "Legend of Zelda", "Super Mario 64" };
public async IAsyncEnumerable<string> GetGames()
{
foreach (var game in games)
{
await Task.Delay(1000);
yield return game;
}
}
Run Code Online (Sandbox Code Playgroud)
剃刀页面中的示例:
@await foreach(var game in GameService.GetGames())
{
<p>@game</p>
}
Run Code Online (Sandbox Code Playgroud)
这会产生错误 CS4033:'await' 运算符只能在异步方法中使用。考虑使用“async”修饰符标记此方法并将其返回类型更改为“Task”。
如果可能的话,有什么想法吗?
I encountered an interesting behavior while exploring IAsyncEnumerable in an ASP.NET Web API project. Consider the following code samples:
// Code Sample 1
[HttpGet]
public async IAsyncEnumerable<int> GetAsync()
{
for (int i = 0; i < 10; i++)
{
await Task.Delay(1000);
yield return i;
}
}
// Code Sample 2
[HttpGet]
public async IAsyncEnumerable<string> GetAsync()
{
for (int i = 0; i < 10; i++)
{
await Task.Delay(1000);
yield return i.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
Sample 1 (int array) returns {} as …
我有以下方法可以从 http 流中读取 csv 文档
public async IAsyncEnumerable<Line> GetLines([EnumeratorCancellation] CancellationToken cancellationToken)
{
HttpResponseMessage response = GetResponse();
using var responseStream = await response.Content.ReadAsStreamAsync();
using var streamReader = new StreamReader(responseStream);
using var csvReader = new CsvReader(streamReader);
while (!cancellationToken.IsCancellationRequested && await csvReader.ReadAsync())
{
yield return csvReader.GetRecord<Line>();
}
}
Run Code Online (Sandbox Code Playgroud)
以及其他地方使用结果的方法
var documentAsyncEnumerable = graphClient.GetLines(cancellationToken);
await foreach (var document in documentAsyncEnumerable.WithCancellation(cancellationToken))
{
// Do something with document
}
Run Code Online (Sandbox Code Playgroud)
我的问题是我应该在一个地方使用取消令牌吗?应该在产生记录之前对取消令牌采取行动还是 IAsyncEnumerable.WithCancellation() 基本上做同样的事情?如果有的话有什么区别?
我们最近将使用的 ASP.NET Core API 迁移Dapper到 .NET Core 3.1。迁移后,我们觉得有机会为我们的一个端点使用最新IAsyncEnumerable功能C# 8。
这是更改前的伪代码:
public async Task<IEnumerable<Item>> GetItems(int id)
{
var reader = await _connection.QueryMultipleAsync(getItemsSql,
param: new
{
Id = id
});
var idFromDb = (await reader.ReadAsync<int?>().ConfigureAwait(false)).SingleOrDefault();
if (idFromDb == null)
{
return null;
}
var items = await reader.ReadAsync<Item>(buffered: false).ConfigureAwait(false);
return Stream(reader, items);
}
private IEnumerable<Item> Stream(SqlMapper.GridReader reader, IEnumerable<Item> items)
{
using (reader)
{
foreach (var item in items)
{
yield return item;
}
}
}
Run Code Online (Sandbox Code Playgroud)
之后 …
如何比较以下两个?Rx 更强大吗?
反应式扩展:
var observable = Observable.Create<char>(async (observer, cancel) =>
{
while (true)
{
string line = await sr.ReadLineAsync();
if (line == null)
break;
observer.OnNext(line);
}
});
observable.Subscribe(
c => Console.WriteLine(c.ToString()),
() => end.Dispose());
Run Code Online (Sandbox Code Playgroud)
异步流:
public async void Run(string path)
{
await foreach (var line in TestAsync())
{
Console.WriteLine(line);
}
}
private async IAsyncEnumerable<string> TestAsync()
{
while (true)
{
string line = await sr.ReadLineAsync();
if (line == null)
break;
yield return line;
}
}
Run Code Online (Sandbox Code Playgroud) 采取以下方法:
public async IAsyncEnumerable<int> Foo()
{
await SomeAsyncMethod();
return Bar(); // Throws since you can not return values from iterators
}
public async IAsyncEnumerable<int> Bar()
{
for(int i = 0; i < 10; i++)
{
await Task.Delay(100);
yield return i;
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道最好的做法是什么,上面的代码试图做什么。IAsyncEnumerable基本上从方法返回一个async。
对于我自己来说,我可以想象两种方式:
IAsyncEnumerable并立即返回结果。await foreach(var item in Bar())
{
yield return item;
}
Run Code Online (Sandbox Code Playgroud)
IAsyncEnumerable,这似乎是更好的解决方案,但仍然有点矫枉过正。return new AsyncEnumerableHolder<int>(Bar());
public struct AsyncEnumerableHolder<T>
{
public readonly IAsyncEnumerable<T> Enumerable;
public AsyncEnumerableHolder(IAsyncEnumerable<T> enumerable)
{
Enumerable …Run Code Online (Sandbox Code Playgroud) iasyncenumerable ×10
c# ×9
c#-8.0 ×6
async-await ×3
asp.net-core ×2
.net-core ×1
blazor ×1
c#-5.0 ×1
dapper ×1
ienumerable ×1
linq ×1
razor-pages ×1
unit-testing ×1