1

Есть WinForms клиент, функция которого обрабатывать файлы из определенной папки пользователя, шифровать, запаковывать их определенным образом и отправлять полученный пакет на wcf сервис. Этот клиент уже был написан, у меня задача его ускорить.


Вот мои мысли и попытки:

  1. Пул Task-ов. Его архитектура построена на пуле Task-ов. То есть документы на обработку складываются в очередь. Затем ранее запущенный Task, внутри которого цикл while(true), следит за этой очередью - берет первый документ, ищет или ждет для него свободный Task из массива пула тасков и дает таску задание:

    TasksPool[index] = Task.Factory.StartNew(() => document.Work(), _cancelWork);

В методе происходил метод отправки документа на сервис:

wcfServiceClient.SendDocument(packet);

У меня возникли в голове такие мысли: когда Task доходит до отправки документа на сервис, и происходит отправка, он тормозит процесс(процесс с этим таском просто зависает и ждет завершения отправки) или как-то сам по умному уходит в ожидание, а его процесс подхватывает в это время работу другого таска? А также возникла мысль что зачем нужно использовать какой-то пул потоков, когда есть готовые средства распараллеливания типа Parallel?

  1. Попытка написать с Parallel.ForEach.

    Parallel.ForEach(files, file => new Document(wcfClient, file).Work())

Просто скажу что лучше не стало, то есть например пул задач для 3-х тасков из 1-го пункта оказался быстрее, чему я очень удивлен. Есть предположение что затык в wcf клиенте...

  1. async await

    class Document { public async Task<bool> Work() { var sendDocumentResult = await _photonServiceClient.SendDocumentAsync(edtPacket); return sendDocumentResult.Result; } }

    var tasks = files.Select(x => new Document(wcfClient, x).Work()); await Task.WhenAll(tasks);

Думал что это решит проблему и процесс не будет простаивать при отправке документа - на деле также никаких преимуществ не дало, работает на уровне 2-го пункта. И теперь я немного в смятении - получается простоев при отправке пакета на сервис не было, уже самый первый вариант работал как нужно? И если 1-й вариант работает быстрее остальных, то значит дело в wcf клиенте, в идеале нужно каждый instance на каждый поток? Но как это соорудить если мы работаем с тасками и не знаем в каком потоке мы фактически выполняемся и сколько потоков будет задействовано?

Winsfox
  • 53
  • в третьем случае нужно избавится от .Result; - это превращает метод в синхронный. и второе: ты можешь создать столько тасков сколько захочешь. если задача ожидает пакетов от сети (i/o bound) - она ресурсов не ест. третье: не понял как ты следил за тасками в цикле? - это buisy wait? – dgzargo Jun 19 '19 at 18:49
  • @dgzargo он там ожидал завершения таска перед тем, как result вызвать – tym32167 Jun 19 '19 at 18:51
  • вот пример асинхронного парсера. Но имейте ввиду, что если у вас большая часть времени тратится на вызов сервиса, то хоть как изголяйся, вызов сервиса с клиента не ускорить – tym32167 Jun 19 '19 at 18:52
  • @tym32167 именно! и метод стал синхронный! – dgzargo Jun 19 '19 at 18:52
  • @dgzargo не стал, если к моменту вызова result таска уже завершилась – tym32167 Jun 19 '19 at 18:53
  • @dgzargo погодите ка, я не понял код автора, он ждет таску, которая возвращает таск походу. Если так, то вы правы ))) – tym32167 Jun 19 '19 at 18:54
  • @tym32167 судя по названию метода, он работает с сетью. а у нее пинг >10мс – dgzargo Jun 19 '19 at 18:56
  • не понимаю как он смог скомпилировать такой метод – dgzargo Jun 19 '19 at 18:57
  • @dgzargo не, я про то, что вот эта строчка var sendDocumentResult = await _photonServiceClient.SendDocumentAsync(edtPacket); дожидается конца таска, то есть в sendDocumentResult после этого должен быть результат таска после выполнения асинхронной операции. Если жто так, то тогда тип этой переменной не таск, и вот это sendDocumentResult.Result к таскам не относится вообще – tym32167 Jun 19 '19 at 18:58
  • @tym32167 кажется я понял про что ты. он не должен был использовать async/await а вернуть сконфигуренный таск. – dgzargo Jun 19 '19 at 19:03
  • @tym32167 так пока тачка с await не завершилась и мы дошли до результата этой тачки я так понимаю что контекст синхронизации в это время перекидывает наш процесс на работу другой тачки, то есть процесс не простаивает. Или я ошибаюсь? – Winsfox Jun 19 '19 at 19:07
  • Спасибо за ответы, я приду домой и ещё раз проверю, попробую переписать с await-ами – Winsfox Jun 19 '19 at 19:10
  • Если вы ждете такск вот так myTask.Result - вы заблочили текущий тред, это плохо. Если вы ждете таск вот так var something = await myTask; - вы ждете асинхронно, то есть не блокируете эти ожиданием поток. – tym32167 Jun 19 '19 at 19:10

0 Answers0