优化缓冲样本以进行并行执行

时间:2013-01-17 19:30:52

标签: c# multithreading

我有这个缓冲算法

while (aufnahme || ArrayAnsammlung.Count > 1)
{
    if (ArrayAnsammlung != null)
    {
        int l = ArrayAnsammlung.Count - 1;
        //db(l.ToString());


        for (int DurchLaeufer = 0; DurchLaeufer < l; DurchLaeufer++)
        {
            if (ArrayAnsammlung[DurchLaeufer] != null)
            {
                Nummerierung = Convert.ToString(Nummerierungszaehler);
                Enkodierung = new JpegBitmapEncoder();
                Enkodierung.FlipHorizontal = true;
                //Enkodierung.FlipVertical = false;
                var dateiStrom = new FileStream("E:\\Temp\\" + datum + " " + Nummerierung.PadLeft(12, '0') + ".jpg", FileMode.Create);
                Enkodierung.Frames.Add(BitmapFrame.Create(BitmapSource.Create(bildbreite, bildhoehe * 2,
                96, 96, PixelFormats.Bgr32, null, ArrayAnsammlung[DurchLaeufer], stride)));
                Enkodierung.Save(dateiStrom);
                dateiStrom = null;
                Enkodierung = null;
                Nummerierungszaehler++;
            }
        }
        if (l > 0)
        {
            ArrayAnsammlung.RemoveRange(0, l);
        }
    }
    Thread.Sleep(60);
}
  • DurchLaeufer只是一个索引。
  • ArrayAnsammlung是一个包含每个字段中的图像数据的数组。所以 for 部分遍历字节数组内容。
  • 这一切都发生在一个线程中,而另一个线程中的图像正在写入ArrayAnsammlung。缓冲区是必要的,因为传递的图像多于处理的图像(转换为jpeg)。
  • aufnahme是一个bool,当图像数据被写入ArrayAnsammlung时为真。
  • Nummerierung是一个帮助分离图像的计数器

它有效,但根据剖析器,它有很高的负载

while (aufnahme || ArrayAnsammlung.Count - 1 > 0)

它使应用程序表现出延迟。

我怎样才能优化它,或者特别是使用Parallel.For这样做而不会弄乱订单。因此,在并行执行时,顺序必须与for循环中的顺序相同。

PS:我添加了

Thread.Sleep(60);

这有助于减少工作量吗?

2 个答案:

答案 0 :(得分:3)

  

while (aufnahme || ArrayAnsammlung.Count - 1 > 0)

附近有很高的负荷

这意味着当Array为空时它会循环很多。您可以使用WaitHandle解决此问题,没有理由在空集合上浪费CPU。

但更好更简单的解决方案是在此使用ConcurrenQueue<T>BlockingCollection。然后,您可以使用myQueue.Take()解决此特定问题。


好的,请求的代码示例:

//untested

// the new definition
private BlockingCollection<byte[]> ArrayAnsammlung = new BlockingCollection<byte[]>();


while (aufnahme)
{
   byte[] data = ArrayAnsammlung.Take();

   if (data != null)
   {
     int localNum = Interlocked.Increment(ref Nummerierung);  // initialize it 1 lower

      ... // process data
   }
}

这是一个粗略的想法。您可能想要查看CompleteAdding()停止的结果。


附带问题:

while (aufnahme || ArrayAnsammlung.Count - 1 > 0)
{
    if (ArrayAnsammlung != null)
    {

!= null测试为时已晚,您已在周围循环中使用.Count

答案 1 :(得分:0)

你为什么不尝试:

Thread.Sleep(0);

MSDN:“指定零(0)表示应该暂停此线程以允许其他等待线程执行。”