我使用Visual Studio 2012在C#(WinForm)中编写了一个小工具。
其目的是让用户针对数据库检查给定的城市和邮政编码,以验证城市/邮编组合是否合法。
到目前为止一切正常(请参阅下面的简化代码)。由于用户可能同时执行多个验证,我使用了队列模式(为了确保,我按照正确的顺序发送多个请求,因为它们已经提交)。
现在,我需要修改我的代码以运行3个Web请求以获得相同的结果。
我不需要直接使用城市和邮政编码查询网络服务,而是需要按顺序发出3个请求:
显然,我必须先等待第一个请求才能继续执行第二个请求,等等......我需要检查第二个请求是否返回true / valid否则我不会需要保存/执行第三个请求。
我需要有关如何在我的代码中包含这两个Web请求而不破坏我的队列机制的帮助。我的队列中的一个项目现在应该包含3个请求,同时确保我没有在步骤1或步骤2之前请求步骤2或3已经发送了(有效)结果。
这是我到目前为止所得到的:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Threading;
using System.Web;
using System.Xml;
using System.Globalization;
using System.Security.Cryptography;
using System.Windows.Forms;
using CheckAddress.Util;
namespace CheckAddress.Api
{
public class ApiHelper
{
#region singleton
private static ApiHelper _instance;
private static Object _lock = new object();
public static ApiHelper Instance
{
get
{
lock (_lock)
{
if (_instance == null)
{
_instance = new ApiHelper();
}
}
return _instance;
}
}
#endregion
private Thread _queueThread;
private bool _running;
private Queue<Address> _queue;
private ApiHelper()
{
_running = false;
_queue = new Queue<Address>();
MaxThreads = SettingsFile.Instance.MaxThreads;
MaxAttempts = SettingsFile.Instance.MaxAttempts;
ThreadPool.SetMaxThreads(MaxThreads, MaxThreads);
}
public int MaxThreads { get; set; }
public int MaxAttempts { get; set; }
public void Add(Address a)
{
lock (_queue)
{
_queue.Enqueue(a);
}
}
private void AddressSendProc(object state)
{
bool isValid = false;
foreach (Address.CityZIP theCityZIP in a.listOfAddresses)
{
while (!success && tries < MaxAttempts)
{
try
{
var req = (HttpWebRequest)WebRequest.Create("http://domain.com/geo.php?city=auburn&zip=95602");
req.Method = "GET";
req.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0) Gecko/20100101 Firefox/4.0";
req.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
req.ContentType = "application/x-www-form-urlencoded";
req.Timeout = 3000;
var resp = (HttpWebResponse)req.GetResponse();
var ms = new MemoryStream();
var rs = resp.GetResponseStream();
if (rs != null)
{
var buf = new byte[4096];
int len = 0;
while ((len = rs.Read(buf, 0, buf.Length)) > 0)
{
ms.Write(buf, 0, len);
}
rs.Close();
}
var xml = new XmlDocument();
xml.LoadXml(Encoding.UTF8.GetString(ms.ToArray()));
var nodes = xml.SelectNodes("/response/valid");
if (nodes.Count == 1)
{
isValid = true;
}
int code = 0;
Int32.TryParse(nodes[0].InnerText, out code);
if (code == 200)
{
success = true;
}
}
catch (Exception ex)
{
/* */
}
tries++;
}
}
}
private void ApiThreadProc()
{
while (_running)
{
try
{
lock (_queue)
{
while (_queue.Count > 0)
{
ThreadPool.QueueUserWorkItem(AddressSendProc, _queue.Dequeue());
}
}
Thread.Sleep(1000);
}
catch (Exception) {/*ignore*/}
}
}
public void Start()
{
_running = true;
_queueThread = new Thread(ApiThreadProc);
_queueThread.Start();
}
public void Stop()
{
_running = false;
if (_queueThread != null)
{
_queueThread.Interrupt();
}
}
}
}