假设我有一个像this这样的生产者 - 消费者模式。该帖子还解释了为什么在这种特定情况下使用TPL Dataflow可能不是最佳的。这就是为什么这个问题改为使用任务。
+----------+ +----------------+ +-----------+
| Task | | Task | | Task |
|Read files|-----BlockingCollection-->|Process values |----BlockingCollection---->|Write files|
+----------+ | |of data logger 1| | +-----------+
| +----------------+ |
| +----------------+ |
| | Task | |
|-BlockingCollection-->|Process values |--|
| |of data logger 2| |
| +----------------+ |
... (n Tasks) ...
在此实现中,读取和写入需要与处理同时发生,因此每个都使用Task来实现此目的。如果我使用阻塞函数进行读写,那么这将是一种方法,但异步读/写怎么样?现在我想知道在这种特定情况下我是否理解正确使用async-await。由于我需要并行性,因此读取和写入仍应在单独的Task中进行。我不想在等待I / O结果时浪费CPU周期,因此async-await似乎是解决方案。
以此伪实现为例。 ReadAllLinesAsync将是一个类似this
的实现BlockingCollection<string []> queue = new BlockingCollection<string []>(100);
var pathsToFiles = files;
await Task.Run(async () =>
{
//This is a dummy for the "Read files"-object's function call
for(int i=0; i<pathsToFiles.Length; i++)
{
string[] file = await ReadAllLinesAsync(pathsToFiles[i]);
queue.Add(file);
}
queue.CompleteAdding();
}
第一个问题是,示例代码是否正确使用async-await? 第二个问题是,与阻塞I / O相比,这是否提高了效率,是否阻止了CPU等待I / O?
我阅读了几篇文章并发布了async-await主题,并且不得不说这是非常复杂的所有做法和不做。具体来说,我读过Steven Cleary的articles。
答案 0 :(得分:0)
使用await
来执行IO时保存线程是正确的。它是否会让你获得任何东西取决于线程是否是你的稀缺资源。
如果线程池过载,这可能会有很大帮助。另一方面,如果线程池过载,您可能无论如何都要超额订阅磁盘。您可以通过使用await SemaphoreSlim.WaitAsync()
等内容限制未完成IO的数量来提高磁盘使用率。
IO效率不受呼叫方式(同步或异步)的影响。通常,异步IO使用更多的CPU,这在这里可以忽略不计,因为IO成本占主导地位。
这是一个GUI场景吗?否则我不明白使用await Task.Run
。