Использовать асинхронные делегаты или ThreadPool.QueueUserWorkItem для массового параллелизма?

StackOverflow https://stackoverflow.com/questions/192539

Вопрос

У меня есть .NET-приложение, которое обрабатывает около 300 000 записей при пакетном импорте, и на каждую запись требуется несколько секунд, поэтому я хотел бы распараллелить это.В следующем коде, в чем разница между ProcessWithAnsycDelegates() и ProcessWithThreadPool()?

public class ResultNotification
 { public EventHandler event Success;
   public EventHandler event Fail;
   internal void Notify(bool sucess) {if (success) Success(); else Fail();}
 }

public static class Processor
 { public ResultNotification ProcessWithAnsycDelegates(Record record)
    { var r = new ResultNotification();
      Func<Record,bool> processRecord=new RecordProcessor().ProcessRecord;
      processRecord.BeginInvoke
                     ( record
                      ,ar => result.Notify(processRecord.EndInvoke(ar))
                      ,null); 
      return r;    
    }

   public ResultNotification ProcessWithThreadPool(Record r)
    { var r  = new ResultNotification();
      var rp = new RecordProcessor();
      ThreadPool.QueueWorkUserItem(_=>result.Notify(rp.ProcessRecord(r)));
      return r;
    }
 }
Это было полезно?

Решение

В этом случае не так много, так как они оба используют пул потоков под капотом. Я бы сказал, что QueueUserWorkItem () легче читать и видеть, что происходит по сравнению с BeginInvoke.

Эта ссылка может помочь. Это старая информация, но все еще в основном применима http://www.yoda.arachsys.com/csharp/threads/threadpool.shtml

Другие советы

Буквальный ответ на вопрос заключается в том, что оба используют threadpool, так что разница невелика, если единственным соображением является производительность.

Если вопрос действительно заключается в получении наилучшей производительности, то может помочь узнать, что при использовании threadpool действительно есть проблемы.К ним относятся:

  • Блокировка конфликта в рабочей очереди
  • Чрезмерное переключение контекста.Если у вас есть 2 процессора и последовательность рабочих элементов, то 25 потоков на самом деле не помогут.Лучше иметь 2 потока, по одному для каждого процессора

Возможно, стоит изучить TPL и PLINQ:

Одним из примеров используемого TPL, который они приводят, является:

for (int i = 0; i < 100; i++) { 
  a[i] = a[i]*a[i]; 
}

Для:

Parallel.For(0, 100, delegate(int i) { 
  a[i] = a[i]*a[i]; 
});
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top