#c# #multithreading #task #threadpool #blockingcollection
#c# #многопоточность #задача #threadpool #blockingcollection
Вопрос:
Я пишу приложение, в котором у меня есть класс Rechnungsleser
с 2 методами и некоторыми полями. Поля:
invoices = new BlockingCollection<Invoice>(new ConcurrentQueue<Invoice>());
// Total number of invoices in the XML
invoicesToProcess = XDocument.Load(sourceFile).Root.Elements().Count();
// Number of invoices consumed
invoicesProecessed = 0;
public void ReadRechnungslauf() (below)
using (XmlReader rechnungsreader = XmlReader.Create(sourceFile))
{
// Iterate over whole file
while (!rechnungsreader.EOF)
{
if (someCondition)
{
XElement rechnung = XNode.ReadFrom(rechnungsreader) as XElement;
// Some minor change
Helper.RemoveAllNamespaces(rechnung);
if (rechnung != null)
{
try
{
// Decent change, takes XElement, reads and changes some Elements, return object of type Invoice
invoices.Add(CreateRechnung(rechnung, possibleOverlays));
}
catch (Exception e)
{
Log(e)
throw;
}
}
}
else
{
rechnungsreader.Read();
}
}
}
public void ProcessRechnungslauf()
{
Rechnung currentRechnung;
// Check that all invoices are processed
while (invoicesToProcess != invoicesProecessed)
{
// Take next enqueued item
currentRechnung = rechnungen.Take();
if (currentRechnung.PrintMode.Equals("Online"))
{
// Very computing heavy method
printer.PrintRechnung(currentRechnung);
}
invoicesProcessed ;
}
}
Я инициализирую оба метода следующим образом:
using (Rechnungsleser reader = new Rechnungsleser()
{
Task readingTask = Task.Factory.StartNew(() =>
{
reader.ReadRechnungslauf();
});
Task processingTask = Task.Factory.StartNew(() =>
{
reader.ProcessRechnungslauf();
});
Task.WaitAll(readingTask, processingTask);
}
Когда я проверяю журнал, он сначала считывает все счета и помещает их в очередь, а затем начинает их обработку. Как я могу обеспечить параллелизм? Это только потому, что ProcessRechnungslauf()
тогда требуется гораздо большая производительность ReadRechnungslauf()
?
Должен ли я использовать Threads
или TaskParallelLibrary
? Почему?
Насколько я понимаю, a Task
берет доступное Thread
из Threadpool
и выполняет его. Я не понимаю, почему эти две задачи не должны работать вместе.
Комментарии:
1. Предоставленного кода недостаточно для принятия каких-либо решений. Неясно, что происходит внутри
ReadRechnungslauf
, каковы переменныеinvoicesToProcess
иinvoicesProecessed
.2. Добавлено больше кода, я не думаю, что это особенно описательно, поскольку на самом деле не так много того, что происходит в
ReadRechnungslauf
3. Хм, похоже на простой шаблон производителя-потребителя. Но ProcessRechnungslauf() должен выполнять счета. Возьмите() вместо rechnungen. Take(), поскольку rechnungen неизвестен в соответствии с вашим примером кода. Вы пытались заменить if (currentRechnung. Режим печати){ … } с помощью какого-либо другого кода, чтобы проверить, есть ли что-то блокирующее / замедляющее работу?
4. Кроме того, попробуйте пометить два потока как продолжительные с помощью
TaskCreationOptions.LongRunning
.5. Как только у вас нет никакого ведения журнала внутри,
ProcessRechnungslauf
я предполагаю, что это происходит где-то внутриPrintRechnung
. Высока вероятность того, что задачи на самом деле запускаются параллельно, но поскольку синтаксический анализ данных является более быстрым процессом, он быстро печатает все свои сообщения в журнал, в то время как длительное выполнениеPrintRechnung
начинает печатать в журнал с некоторого момента, который происходит позже, чемReadRechnungslauf
завершается.