Несколько потоков в веб-сервисе - PullRequest
0 голосов
/ 20 ноября 2011

У меня есть работающий веб-сервис, который при загрузке связывается с разными веб-сайтами и собирает с них соответствующую информацию.По мере роста требований росло и количество httpwebrequests.

В настоящее время я не использую никаких асинхронных запросов в веб-сервисе, что означает, что ASP.net обрабатывает один запрос за раз.Это, очевидно, стало бременем, поскольку один запрос к самому веб-сервису может занять до 2 минут.

Есть ли способ преобразовать все эти httpwebreqeusts внутри веб-службы в многопоточную?

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

Спасибо!

1 Ответ

0 голосов
/ 20 ноября 2011

Если вы работаете с .Net V4 +, вы можете использовать библиотеку Parallel или библиотеку задач, которая позволяет легко делать такие вещи.

Если вы вызываете все свои веб-службы одним и тем же способом (при условии, что все веб-службы уважают один и тот же WSDL, только разные URL-адреса, вы можете использовать что-то вроде этого):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;

namespace ConsoleApplication2
{
    class Program
    {
        private const string StartUrl = @"http://blog.hand-net.com";

        private static void Main()
        {
            var content = DownloadAsString(StartUrl);

            // The "AsParallel" here is the key
            var result = ExtractUrls(content).AsParallel().Select(
                link =>
                {
                    Console.WriteLine("... Fetching {0} started", link);
                    var req = WebRequest.CreateDefault(new Uri(link));

                    var resp = req.GetResponse();

                    var info = new { Link = link, Size = resp.ContentLength};

                    resp.Close();

                    return info;
                }
                );

            foreach (var linkInfo in result)
            {

                Console.WriteLine("Link : {0}", linkInfo.Link);
                Console.WriteLine("Size : {0}", linkInfo.Size);
            }
        }

        private static string DownloadAsString(string url)
        {
            using (var wc = new WebClient())
            {
                return wc.DownloadString(url);
            }
        }

        private static IEnumerable<string> ExtractUrls(string content)
        {
            var regEx = new Regex(@"<a\s+href=""(?<url>.*?)""");
            var matches = regEx.Matches(content);

            return matches.Cast<Match>().Select(m => m.Groups["url"].Value);
        }
    }
}

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

Этот код не имеет обработки ошибок, функции отмены, но иллюстрирует метод AsParallel.

Если вы не можете вызывать все ваши веб-сервисы одинаково, вы также можете использовать что-то вроде этого:

        Task.WaitAll(
            Task.Factory.StartNew(()=>GetDataFromWebServiceA()),
            Task.Factory.StartNew(()=>GetDataFromWebServiceB()),
            Task.Factory.StartNew(()=>GetDataFromWebServiceC()),
            Task.Factory.StartNew(()=>GetDataFromWebServiceD()),
            );

Этот код добавит 4 задачи, которые будут запускаться «когда это возможно». Метод WaitAll просто будет ожидать завершения всей задачи перед возвратом.

Под возможной я подразумеваю, когда слот в пуле потоков свободен. При использовании библиотеки задач для каждого ядра процессора по умолчанию используется один пул потоков. Если у вас есть 100 задач, 100 тактов будут обрабатываться 4 рабочими потоками на 4-ядерном компьютере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...