我有以下代码:
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表达式仍然被执行。它是如何工作的?
我担心的另一个问题是关于多线程的。我听说过很多次async!= multithreading。那么,为什么Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
会输出各种ID呢?其中一些ID被多次打印,但总体上输出了大约5个线程ID。我的代码没有显式地创建任何线程。所有都是异步等待。
StringBuilder
不支持多线程,我想了解上面的实现是否有效。
请忽略我的代码算法,它并不真正重要,这只是一个示例。重要的是使用System.Async.Linq。
StringBuilder
不支持多线程? - mnjStringBuilder
会没问题吗? - mnjParallel.ForEachAsync
并行进行调用。LINQ Async可用于过滤或转换,但不能用于实际并发执行任务。 - Panagiotis Kanavos