Web服务中的多个线程

时间:2011-11-20 13:03:50

标签: asp.net web-services asynchronous httpwebrequest

我有一个有效的网络服务,负载联系不同的网站,并从中抓取相关信息。随着需求的增长,httpwebrequests的数量也在增加。

现在我没有在Web服务中使用任何异步请求 - 这意味着ASP.net一次呈现一个请求。这显然成了一个负担,因为对Web服务本身的一个请求可能需要2分钟才能完成。

有没有办法将webservice中的所有httpwebreqeusts转换为多线程?

实现这一目标的最佳方式是什么?

谢谢!

1 个答案:

答案 0 :(得分:0)

如果您正在使用.Net V4 +,您可以使用并行库或任务库来轻松执行此类操作。

如果您使用相同的方式调用所有Web服务(假设所有Web服务都遵循相同的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允许以并行方式运行select的内容。

此代码没有错误处理,取消功能,但说明了AsParallel方法。

如果您无法以相同的方式呼叫所有的网络服务,您也可以使用以下内容:

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

此代码将添加4个任务,这些任务将在“可能的时候”运行。 WaitAll方法将在返回之前等待所有任务完成。

在可能的情况下,我的意思是线程池中的一个插槽是空闲的。使用任务库时,默认情况下每个处理器核心有一个线程池。如果您有100个任务,则4个核心计算机上的4个工作线程将处理100个任务。