c语言获取进程内存(C学习异步函数)
在C#8之前,可以使用yield return实现迭代器,也可以用await书写异步函数。但无法两者结合,实现一个可以等待的迭代器。C#8引入了异步流解决了这个问题。
异步流基于以下两个接口。
public interface IAsyncEnumerable<out T>
{
IAsyncEnumerator<T> GetAsyncEnumerator(...);
}
public interface IAsyncEnumerator<out T>
: IAsyncDisposable
{
T Current { get; }
ValueTask<bool> MoveNextAsync();
}
ValueTask<T>结构体封装了Task<T>,其行为和Task<T>相似。在任务对象同步完成的情况下具有更好的执行性能。
结合使用迭代器和异步方法的规则来书写方法就可以创建一个异步流。即该方法应同时具备yield return和await,并且返回值为IAsyncEnumerable<T>:
async IAsyncEnumerable<int> RangeAsync (
int start, int count, int delay)
{
for (int i = start; i < start count; i )
{
await Task.Delay (delay);
yield return i;
}
}
相应地,使用await foreach语句就可以消费异步流:
await foreach (var number in RangeAsync (0, 10, 500))
{
Console.WriteLine (number);
}
以上例子,数据持续以每0.5秒一个的速度到达。 而如果像以下例子中使用Task<IEnumerable<T>>,则只有所有数据都准备好时才会最终返回:
static async Task<IEnumerable<int>>
RangeTaskAsync(int start, int count, int delay)
{
List<int> data = new List<int>();
for (int i = start; i < start count; i )
{
await Task.Delay (delay);
data.Add (i);
}
return data;
}
消费上例中的结果只需使用foreach语句即可:
foreach (var data in await RangeTaskAsync(0, 10, 500))
{
Console.WriteLine (data);
}
System.Linq.Async Nuget包包含了对IAsyncEnumerable<T>查询的LINQ查询运算符。这样就可以像查询IEnumerable<T>那样书写查询了。 例如,可以对前面RangeAsync方法书写LINQ查询:
IAsyncEnumerable<int> query =
from i in RangeAsync (0, 10, 500)
where i % 2 == 0
select i * 10;
await foreach (var number in query)
{
Console.WriteLine (number);
}
ASP.NET Core控制器的方法目前支持返回IAsyncEnumerable<T>对象了,此类方法必须标记async:
[HttpGet]
public async IAsyncEnumerable<string> Get()
{
using var dbContext = new DbContext();
await foreach (var title in dbContext.Books
.Select(b=>b.Title).AsAsyncEnumerable())
{
yield return title;
}
}
免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com