Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用异步等待为并行生产者消费者运行I/O的任务_C#_.net_Asynchronous_Parallel Processing_Async Await - Fatal编程技术网

C# 使用异步等待为并行生产者消费者运行I/O的任务

C# 使用异步等待为并行生产者消费者运行I/O的任务,c#,.net,asynchronous,parallel-processing,async-await,C#,.net,Asynchronous,Parallel Processing,Async Await,假设我有一个生产者-消费者模式,如。这篇文章还解释了为什么在这种特定情况下使用TPL数据流可能不是最优的。这就是为什么这个问题使用任务来代替 +----------+ +----------------+ +-----------+ | Task | | Task |

假设我有一个生产者-消费者模式,如。这篇文章还解释了为什么在这种特定情况下使用TPL数据流可能不是最优的。这就是为什么这个问题使用任务来代替

+----------+                          +----------------+                           +-----------+ 
|   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)        ...
在这个实现中,读和写需要在处理过程中同时发生,因此每个过程都使用一个任务来完成。如果我将使用阻塞函数进行读写,这将是一种方法,但是异步读/写呢?现在,我想知道我是否正确理解了async Wait的用法,在这种特定情况下。由于我需要并行性,读写操作仍应在单独的任务中进行。我不想把CPU周期浪费在等待I/O结果上,所以异步等待似乎是解决方案

以这个伪实现为例。ReadAllLinesAsync将是一个如下的实现

BlockingCollection队列=新的BlockingCollection(100);
var pathsToFiles=文件;
等待任务。运行(异步()=>
{
//这是“读取文件”对象函数调用的虚拟对象

对于(int i=0;i在执行IO时使用
wait
保存线程是正确的。它是否能为您带来任何好处取决于线程是否是您的稀缺资源

如果线程池过载,这会有很大帮助。另一方面,如果线程池过载,您可能还是超额订阅了磁盘。您可以通过使用
wait SemaphoreSlim.WaitAsync()
之类的方法限制未完成的IOs数量来提高磁盘使用率

IO效率不受调用方式(同步或异步)的影响。通常,异步IO使用的CPU稍多一些,这在这里可以忽略不计,因为IO成本占主导地位


这是一个GUI场景吗?否则,我看不到使用
等待任务的意义。运行

您可能想查看它,它使复杂的异步消费者/生产者管道变得更容易。@ScottChamberlain我知道您几天前给了我这个提示,谢谢!问题是它在某种程度上不适合这种特定情况我知道。如果你愿意的话,看看我发布的第一个链接。附言:我真的希望你能看到这个:)@ScottChamberlain我不使用TPL数据流的原因是,我需要并行处理来自数据记录器的值,但每个数据记录器的处理方式不同。在一个数据记录器的处理中,处理必须是顺序的(按时间顺序)。此外,来自读取块的数据需要分发到特定块,条件链接似乎是一种开销。有关详细说明,请参阅我的文章,因为我预计大约有200个数据记录器,每个记录器都有一个处理任务,我猜线程池过载。我只需要一个读取任务和一个任务用于写入。我不确定信号量将如何提高磁盘使用率。你的意思是我应该只允许读或写吗?据我所知,异步和I/O确实通过不阻塞和使用I/O完成端口来提高效率。I/O是生产者-消费者的瓶颈,因为它将是最慢的部分。它将被使用在Windows服务中,我想你可以放弃等待。无论你如何启动IO,磁头都不会以不同的方式移动。你只会看到通过某种方式改进磁头的移动来提高性能。许多并发磁盘IO具有随机化IO的效果,从而破坏性能。这就是为什么你经常需要这样做的原因通过限制DOP(磁盘通常为1)来控制IO.200任务很多,我可以看到异步IO和在这里等待的好例子。
通过不阻塞和使用I/O完成端口来提高效率
das是如何提高效率的?坦率地说,这是一个太模糊的理解。在这里解释它太长了,但你基本上可以忘记这一点。
I/O是一个瓶颈k,因为这将是最慢的部分
正确。因此,任何基于CPU的优化都是毫无意义的。这里最重要的是改进物理IO模式,不要使线程池过载。我认为这对于优化磁头移动来说,级别太低了一点。此外,只要不这样做,这甚至是不可能的为控制器编写自己的固件:)效率会得到提高,因为您不会将CPU周期闲置在等待I/O上,而且据我所知,使用async,您可以充分利用I/O完成端口获得I/O的最大性能。据我所知,您的速度不可能超过这一速度。您唯一可以调整的是缓冲区大小和块的大小g队列。
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();
}