Web 服务中的多个线程

发布于 2024-12-16 19:03:39 字数 255 浏览 1 评论 0原文

我有一个正在运行的网络服务,它在加载时会联系不同的网站并从中抓取相关信息。随着需求的增长,httpweb 请求的数量也随之增加。

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

有没有办法将Web服务内的所有这些httpwebreqeusts转换为多线程?

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

谢谢!

I have a working web service which On load contacts different websites and scrapes relevant information from them. As the requirements grew so did the number of httpwebrequests.

Right now I'm not using any asynchronous requests in the web service - Which means that ASP.net renders one request at a time. This obviously became a burden as one request to the webservice itself can take up to 2 minutes to complete.

Is there a way to convert all these httpwebreqeusts inside the webservice to multi-threaded?

What would be the best way to achieve this?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

◇流星雨 2024-12-23 19:03:39

如果您正在使用 .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 允许以并行方式运行选择的内容。

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

如果您无法以相同的方式调用所有 Web 服务,您还可以使用类似以下内容:

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

此代码将添加 4 个任务,这些任务将“在可能的情况下”运行。 WaitAll 方法将简单地等待所有任务完成然后返回。

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

If you are working with .Net V4+, you can use the Parallel library or task library which allow easily to do such things.

If you call all your web services using the same way (assuming all web services respects the same WSDL, just differing urls, you can use something like this) :

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);
        }
    }
}

This small program first download an html page, then extract all href. This produces an array of remote files.
the AsParralel here allow to run the content of the select in a parallel way.

This code does not have error handling, cancellation feature but illustrate the AsParallel method.

If you can't call all your webservices in the same way, you can also use something like this :

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

This code will add 4 tasks, that will be run "when possible". The WaitAll method will simply wait for all task to be completed before returning.

By when possible I mean when a slot in the thread pool is free. When using the Task library, there is by default one thread pool per processor core. If you have 100 tasks, the 100 taks will be processed by 4 worker threads on a 4 core computer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文