Есть ли способ асинхронно обрабатывать несколько каналов xml? - PullRequest
0 голосов
/ 17 июня 2020

Я использую класс Atom10FeedFormatter для обработки атома xml каналов, вызывающих конечную точку OData Rest API.

Он работает нормально, но API дает медленный результат, если в канале более 200 записей.

Это то, что я использую:

        Atom10FeedFormatter formatter = new Atom10FeedFormatter();

        XNamespace d = "http://schemas.microsoft.com/ado/2007/08/dataservices";

        string odataurl= "http://{mysite}/_api/ProjectData/Projects";

        using (XmlReader reader = XmlReader.Create(odataurl))
        {
             formatter.ReadFrom(reader);
        }

         foreach (SyndicationItem item in formatter.Feed.Items)
         {
              //processing the result
         }

Я хочу ускорить этот процесс, по крайней мере, немного быстрее, разделив исходный запрос на запрос результатов, пропустив некоторые записи и ограничив размер записи.

Основная идея состоит в том, чтобы подсчитать количество каналов с помощью $ count, разделить результаты канала на блоки по 20, использовать $ skip и $ top в URL-адресе конечной точки, перебрать результаты и, наконец, суммировать их.

int countoffeeds = 500; // for the sake of simplicity, of course, i get it from the odataurl using $count
int numberofblocks = (countoffeeds/20) + 1;

for(int i = 0; i++; i<numberofblocks){
    int skip = i*20;
    int top = 20;
    string odataurl = "http://{mysite}/_api/ProjectData/Projects"+"?&$skip="+skip+"&top=20";
    Atom10FeedFormatter formatter = new Atom10FeedFormatter();


    using (XmlReader reader = XmlReader.Create(odataurl))
    {
         formatter.ReadFrom(reader); // And this the part where I am stuck. It returns a void so I 
                                     //cannot use Task<void> and process the result later with await 
    }
...

Обычно я бы использовал вызовы asyn c к api (в данном случае numberofblocks = 26 вызовов параллельно), но я не знаю, как мне это сделать. formatter.ReadFrom возвращает void, поэтому я не могу использовать его с Task.

Как я могу решить эту проблему и как я могу читать несколько каналов xml одновременно?

1 Ответ

1 голос
/ 17 июня 2020

Обычно я бы использовал asyn c вызовы API (в этом случае numberofblocks = 26 вызовов параллельно), но я не знаю, как бы это сделать. formatter.ReadFrom возвращает void, поэтому я не могу использовать его с Task.

Atom10FeedFormatter на данный момент очень устаревший тип, и он не поддерживает асинхронность. И вряд ли он будет обновлен для поддержки асинхронности.

Как я могу решить эту проблему и как я могу читать несколько каналов xml одновременно?

Поскольку вы застряли в синхронном мире, у вас есть возможность использовать «поддельную асинхронность». Это просто означает, что вы выполняете синхронную блокирующую работу в потоке пула потоков и обрабатываете каждую из этих операций, как если бы они были асинхронными. Т.е.:

var tasks = new List<Task<Atom10FeedFormatter>>();
for(int i = 0; i++; i<numberofblocks) {
  int skip = i*20;
  int top = 20;
  tasks.Add(Task.Run(() =>
  {
    string odataurl = "http://{mysite}/_api/ProjectData/Projects"+"?&$skip="+skip+"&top=20";
    Atom10FeedFormatter formatter = new Atom10FeedFormatter();
    using (XmlReader reader = XmlReader.Create(odataurl))
    {
      formatter.ReadFrom(reader);
      return formatter;
    }
  }));
}
var formatters = await Task.WhenAll(tasks);
...