gpt4 book ai didi

c# - 异步 LINQ - 不懒惰?多线程?

转载 作者:行者123 更新时间:2023-12-05 00:50:56 25 4
gpt4 key购买 nike

我有以下代码:

var things = await GetDataFromApi(cancellationToken);

var builder = new StringBuilder(JsonSerializer.Serialize(things));

await things
.GroupBy(x => x.Category)
.ToAsyncEnumerable()
.SelectManyAwaitWithCancellation(async (category, ct) =>
{
var thingsWithColors = await _colorsApiClient.GetColorsFor(category.Select(thing => thing.Name).ToList(), ct);

return category
.Select(thing => ChooseBestColor(thingsWithColors))
.ToAsyncEnumerable();
})
.ForEachAsync(thingAndColor =>
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId); // prints different IDs
builder.Replace(thingAndColor.Thing, $"{thingAndColor.Color} {thingAndColor.Thing}");
}, cancellationToken);

它使用 System.Linq.Async,我觉得很难理解。在“经典”/同步 LINQ 中,整个事情只有在我调用 ToList()ToArray() 时才会执行。在上面的示例中,没有这样的调用,但无论如何都会执行 lambda。它是如何工作的?

我担心的另一个问题是多线程。我多次听到异步!= 多线程。那么,Console.WriteLine(Thread.CurrentThread.ManagedThreadId); 怎么可能打印各种 ID?一些 ID 会被多次打印,但总体而言,输出中大约有 5 个线程 ID。我的代码都没有显式创建任何线程。这都是异步等待。StringBuilder不支持多线程,想了解一下上面的实现是否有效。

请忽略我代码的算法,没关系,只是一个例子。重要的是 System.Async.Linq 的用法。

最佳答案

ForEachAsync 将具有与 ToList/ToArray 类似的效果,因为它强制评估整个列表。

默认情况下,await 之后的任何内容都在相同的执行上下文 上继续,这意味着如果代码在 UI 线程上运行,它将继续在 UI 线程上运行。如果它在后台线程上运行,它将继续在后台线程上运行,但不一定是相同的

但是,您的任何代码都不应并行运行。这并不一定意味着它是线程安全的,可能需要一些内存屏障来确保正确刷新数据,但我认为这些屏障是由框架代码本身发出的。

关于c# - 异步 LINQ - 不懒惰?多线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73496992/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com