如何使用线程和多个HttpWebRequest异步调用创建Windows服务?

时间:2017-08-31 20:40:03

标签: multithreading c#-4.0 windows-services httpwebrequest

我需要帮助使用Threading和异步HttpWebRequest调用创建Windows服务。我之前创建了一些C#windows服务但从未使用过线程。此外,我似乎正忙着使用HttpWebRequest进行异步调用。我已经用Google搜索了这个以及在这个网站上查看。我找不到任何有帮助的东西。这主要是因为我似乎无法将其他问题中的内容用于我的具体示例。

请记住,基于我在这个特定领域缺乏知识以及试图解决问题,我可能会重叠。

主要流程是在onStart期间获取网址列表。通常,此列表将从_facade.GetUrls调用中检索。然后,在每个时间间隔调用scanSites。向每个URL发出请求,然后将结果保存到_facade.SaveUrlResponse中的数据库中。

我的问题是,当我调试它时,似乎我陷入无休止的循环中。我不确定如何/在哪里这样做。提前谢谢。

这就是我所拥有的:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.ServiceProcess;
using System.Threading;
using URLValidation.BusinessManager.Facade;
using URLValidation.BusinessManager.Model;

namespace URLValidation
{
partial class URLValidation : ServiceBase
{
    #region " class variables "        
    private System.Timers.Timer _timer;
    private List<UrlModel> _url_List = null;
    private Facade _facade;
    private Thread _t;
    private int _x;
    #endregion


    public URLValidation()
    {
        _facade = new Facade();
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        try
        {
            _url_List = new List<UrlModel>
                   {
                     new UrlModel(address: "http://www.google.com", addressID: 1),
                     new UrlModel(address: "http://www.microsoft.com", addressID: 2),
                    new UrlModel(address: "http://www.stackoverflow.com", addressID: 3)
                   };

            resetTimer();

            GC.KeepAlive(_timer);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    private void resetTimer()
    {
        try
        {
            _timer = new System.Timers.Timer();
            _timer.Interval = 10000;//1800000; //30 minutes
            _timer.Start();
            _timer.Enabled = true;
            _timer.Elapsed += scanSites;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    private void scanSites(object sender, System.Timers.ElapsedEventArgs e)
    {
        _timer.Stop();
        _x = 0;
        _t = new Thread(new ThreadStart(scanSites));
        _t.IsBackground = true;
        _t.Start();
    }

    private void scanSites()
    {
        try
        {
            foreach (UrlModel url in _url_List)
            {
                _x += 1;
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url.Address);
                request.Method = "HEAD";
                RequestModel requestModel = new RequestModel(request, url);

                IAsyncResult result = request.BeginGetResponse(new AsyncCallback(saveUrlResponse), requestModel);
                ThreadPool.RegisterWaitForSingleObject
                    (
                                    result.AsyncWaitHandle,
                                    new WaitOrTimerCallback(ScanTimeoutCallback),
                                    requestModel,
                                    (30 * 1000),  // 30 second timeout
                                    true
                    );
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    private void saveUrlResponse(IAsyncResult result)
    {
        //grab the custom state object
        RequestModel requestModel = (RequestModel)result.AsyncState;
        HttpWebRequest request = (HttpWebRequest)requestModel.Request;

        //get the Response
        HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);

        // process the response...
        ResponseModel responseModel = new ResponseModel(request, response, requestModel.UrlModel.AddressID);
        _facade.SaveUrlResponse(responseModel);
    }

    private void ScanTimeoutCallback(object requestModel, bool timedOut)
    {
        if (timedOut)
        {
            RequestModel reqState = (RequestModel)requestModel;
            if (reqState != null)
                reqState.Request.Abort();
        }

        if (_x == _url_List.Count)
        {
            resetTimer();
        }
    }

    protected override void OnStop()
    {
        // TODO: Add code here to perform any tear-down necessary to stop your service.
    }
}
}

好的,我想我到了某个地方。我已将代码移至控制台应用程序。我可以使用GetResponse(sync)和BeginGetResponse(async)将结果保存到数据库中。据我所知,我相信这是一个很好的解决方案。有人可以验证这一点,如果您将其移至Windows服务后预见到任何问题,请告诉我。这是新代码

using System;
using System.Collections.Generic;
using System.Net;
using System.Threading;

namespace ConsoleApplication2
{
    static class Program
    {
        private static List<UrlModel> _url_List = null;
        private static Object _acctLock = new object();
        private static Facade _facade = new Facade();

        static void Main(string[] args)
        {
            _url_List = new List<UrlModel>
                {
                    new UrlModel(address: "http://www.microsoft.com", addressID: 1),
                    new UrlModel(address: "http://www.google.com", addressID: 2),
                    new UrlModel(address: "http://www.stackoverflow.com", addressID: 3)
                };

            lockThreadAndGetUrlStatus(_url_List);
            Console.ReadLine();
        }

        static void lockThreadAndGetUrlStatus(List<UrlModel> _url_List)
        {
            Thread[] threads;
            try
            {
                threads = new Thread[_url_List.Count];
                Thread.CurrentThread.Name = "main";
                int i = 0;
                foreach (UrlModel url in _url_List)
                {
                    //Thread t = new Thread(() => scanSites(url));
                    Thread t = new Thread(() => scanSitesWithAsync(url));
                    t.Name = i.ToString();
                    threads[i] = t;
                    i += 1;
                }

                for (i = 0; i < _url_List.Count; i++)
                {
                    Console.WriteLine("Thread {0} Alive : {1}", threads[i].Name, threads[i].IsAlive);
                    threads[i].Start();
                    Console.WriteLine("Thread {0} Alive : {1}", threads[i].Name, threads[i].IsAlive);
                }

                Console.WriteLine("Current Priority : {0}", Thread.CurrentThread.Priority);
                Console.WriteLine("Thread {0} Ending", Thread.CurrentThread.Name);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        static void scanSitesWithAsync(UrlModel url)
        {
            try
            {
                lock (_acctLock)
                {
                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url.Address);
                    request.Method = "HEAD";
                    RequestModel requestModel = new RequestModel(request, url);

                    IAsyncResult result = request.BeginGetResponse(new AsyncCallback(saveUrlResponseWithAsync), requestModel);
                    ThreadPool.RegisterWaitForSingleObject
                    (
                                result.AsyncWaitHandle,
                                new WaitOrTimerCallback(scanTimeoutCallback),
                                requestModel, 30000, true
                    );
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        static void saveUrlResponseWithAsync(IAsyncResult result)
        {
            try
            {
                RequestModel requestModel = (RequestModel)result.AsyncState;
                HttpWebRequest request = (HttpWebRequest)requestModel.Request;

                //get the Response
                HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);

                // process the response...
                ResponseModel responseModel = new ResponseModel(requestModel.Request, response, requestModel.UrlModel.AddressID);
                _facade.SaveUrlResponse(responseModel);
                Console.WriteLine(response.StatusCode);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        static void scanTimeoutCallback(object requestModel, bool timedOut)
        {
            try
            {
                if (timedOut)
                {
                    RequestModel reqState = (RequestModel)requestModel;
                    if (reqState != null)
                        reqState.Request.Abort();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
    }

1 个答案:

答案 0 :(得分:0)

看起来您正在尝试同时发出3个异步请求。默认情况下,HTTP / 1.1协议仅指定2个连接