英文:
Is there any point in using async api
问题
I have data in memory (json strings):
List<string> data = new List<string>();
using (StreamReader sr = new StreamReader("file.txt"))
{
while (sr.Peek() >= 0)
{
data.Add(sr.ReadLine());
}
}
我有存储在内存中的数据(JSON字符串):
List<string> data = new List<string>();
using (StreamReader sr = new StreamReader("file.txt"))
{
while (sr.Peek() >= 0)
{
data.Add(sr.ReadLine());
}
}
and I want to filter these objects using System.Linq.Async:
var filteredData = data.WhereAwait(async x =>
await filters.ToAsyncEnumerable().AllAwaitAsync(async filter =>
(await JsonSerializer.DeserializeAsync<RootDto>(new MemoryStream(Encoding.UTF8.GetBytes(x))))
.Child.Id == filter));
我想使用System.Linq.Async来筛选这些对象:
var filteredData = data.WhereAwait(async x =>
await filters.ToAsyncEnumerable().AllAwaitAsync(async filter =>
(await JsonSerializer.DeserializeAsync<RootDto>(new MemoryStream(Encoding.UTF8.GetBytes(x))))
.Child.Id == filter));
I know this example is stupid, but this is just a general example of whether or not to use an async api in places where it links to a synchronous one. In this example I have List<string> data
which is not async by nature. I understand that it makes more sense in a case when data is obtained from an object also asynchronously.
Is it better than the one above?
var filters = new[] {"U45TC0Y7KLLD", "ELXE5X1IXHZV", "KHI3NXKEN1PE", "A7R5LDD4O0NK", "1TIICSXMH7FJ"};
var filteredData = data.Where(filters.All(filter =>
JsonSerializer.DeserializeAsync<RootDto>(new MemoryStream(Encoding.UTF8.GetBytes(x))).GetAwaiter()
.GetResult().Child.Id == filter));
我知道这个示例很愚蠢,但这只是一个一般性的示例,用来说明是否应该在与同步API链接的地方使用异步API。在这个示例中,我有一个不是自然异步的 List<string> data
。我理解在数据也是异步获取的情况下更有意义。
这个示例是否比上面的示例更好?
var filters = new[] {"U45TC0Y7KLLD", "ELXE5X1IXHZV", "KHI3NXKEN1PE", "A7R5LDD4O0NK", "1TIICSXMH7FJ"};
var filteredData = data.Where(filters.All(filter =>
JsonSerializer.DeserializeAsync<RootDto>(new MemoryStream(Encoding.UTF8.GetBytes(x))).GetAwaiter()
.GetResult().Child.Id == filter));
英文:
I have data in memory (json strings):
List<string> data = new List<string>();
using (StreamReader sr = new StreamReader("file.txt"))
{
while (sr.Peek() >= 0)
{
data.Add(sr.ReadLine());
}
}
and I want to filter these objects using System.Linq.Async:
var filteredData = data.WhereAwait(async x =>
await filters.ToAsyncEnumerable().AllAwaitAsync(async filter =>
(await JsonSerializer.DeserializeAsync<RootDto>(new MemoryStream(Encoding.UTF8.GetBytes(x))))
.Child.Id == filter));
I know this example is stupid, but this is just a general example of whether or not to use an async api in places where it links to a synchronous one. In this example I have List<string> data
which is not async by nature. I understand that it makes more sense in a case when data is obtained from an object also asynchronously.
Is it better than the one above?
var filters = new[] {"U45TC0Y7KLLD", "ELXE5X1IXHZV", "KHI3NXKEN1PE", "A7R5LDD4O0NK", "1TIICSXMH7FJ"};
var filteredData = data.Where(filters.All(filter =>
JsonSerializer.DeserializeAsync<RootDto>(new MemoryStream(Encoding.UTF8.GetBytes(x))).GetAwaiter()
.GetResult().Child.Id == filter));
I want to get explanation
答案1
得分: 0
我知道这个例子很愚蠢。
问题在于愚蠢的例子会让讨论特定问题的解决方案变得困难,因为对于不同变体的问题,可能有多种解决方案。而且你似乎完全不理解异步(GetAwaiter().GetResult()
实在太糟糕了,以至于有一个专门的名字叫做异步覆盖同步反模式)。
至于愚蠢的例子,答案是否定的。通过将你所做的部分标记为“async”(请注意,实际上它并不是异步的,正如我在上面提到的,你只是喜欢这个关键字的外观,所以才添加了它)你不会获得任何好处。
然而,在愚蠢的例子中,有两个理论上可以使用async
的地方:
-
实际读取文件的部分。任何类型的I/O都是
async
的典型应用场景,可以确保你的进程的线程不会闲着,而是在其他系统组件(DMA传输芯片和操作系统调度程序)执行实际工作时能够继续工作。 -
如果你消除了那个可怕的异步覆盖同步的代码,而是创建了并行反序列化代码的个别任务,然后等待它们。可以考虑使用
Task.WhenAll
。根据你要反序列化的项数以及它们的复杂性,这实际上可能会提供吞吐量的好处。
英文:
> I know this example is stupid
The problem is that stupid examples make talking about a specific problem's solution difficult when there are multiple solutions for different variations of said problem. Also it doesn't help that you don't seem to understand async at all (GetAwaiter().GetResult()
is so incredibly bad that there's a name for it, the async-over-sync anti-pattern).
As far as the stupid example goes though, the answer is no. You gain nothing by making the portion you did "async" (note that it's not actually async, as I mentioned above, you just like how the keyword looks so you added it).
There are two theoretical places in the stupid example where async
would be of use however:
-
the part where you actually read the file. I/O of any kind is exactly what
async
is made for, making it so your process' threads aren't just sitting around picking their nose as other system components (the DMA transfer chips and the OS scheduler) do the actual work. -
If you got rid of that terrible async-over-sync code and instead created individual tasks that deserialize the code in parallel, then awaited that. Think
Task.WhenAll
. Depending on how many items you're deserializing and how complex they are, that could actually provide a throughput benefit.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论