我正在编写的应用程序发送存储在数据库中的SMS消息。对于这一部分,我将编写一个windows服务,它将遍历选定的数据库,然后将等待的消息作为HTTP请求发送。
因为应用程序正在发送SMS,所以速度很重要。现在,我每秒只能收到大约15个请求。现在,应用程序创建SMSMessages,然后将它们放入同步队列中。我使用多线程一次运行该队列中的20个线程。
我注意到,如果我运行了太多的线程,那么应用程序实际上会减慢每秒发送的消息数量。
我试图弄清楚的是,是否有比我正在做的更快的方法来发送请求。有没有更好的方法来组织我的线程,或者我应该使用线程池或异步请求来优化应用程序?
主要代码如下:
Queue Messages = new Queue();
DataRow[] Rows = dtSMSCombined.Select(); //Created from a datatable
foreach (DataRow Row in Rows)
{
... //Get information from the row.
SMSMessage oSMS = new SMSMessage(Keyword, Number, Message, MessageID);
Messages.Enqueue(oSMS);
}
Queue SyncedMessages = Queue.Synchronized(Messages);
var tasks = new Task[20];
for (int i = 0; i < 20; i++)
{
tasks[i] = Task.Factory.StartNew(() =>
{ //each thread will pull out new items from the queue as they finish
while (SyncedMessages.Count > 0)
{
Response = new XDocument();
SMSMessage oSMS = (SMSMessage)SyncedMessages.Dequeue();
if (oSMS.GetMessage() != null && oSMS.GetMessage() != string.Empty)
{
Response = oSMS.SendSMS();
}
string ResponseCode = (string)Response.Descendants("response").First();
if (ResponseCode == "ok")
{
oSMS.sResponseCode = ResponseCode;
oSMS.dCompleted = DateTime.Now;
}
else { }
oSMS.DTInsert();
}
});
}
while (tasks.Any(t => !t.IsCompleted)) { }下面是来自SMSMessage类的SendSMS()方法:
public XDocument SendSMS()
{
XML = "<message id=\""+ lMessageID +"\"><partnerpassword>" + PartnerPassword + "</partnerpassword><content>" + sMessage + "</content></message>";
URL = "http://sloocetech.net:****/spi-war/spi/" + PartnerID + "/" + sRecipient + "/" + Keyword + "/messages/mt";
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(URL);
Request.Proxy = null;
RequestBytes = System.Text.Encoding.ASCII.GetBytes(XML);
Request.Method = "POST";
Request.ContentType = "text/xml;charset=utf-8";
Request.ContentLength = RequestBytes.Length;
RequestStream = Request.GetRequestStream();
RequestStream.Write(RequestBytes, 0, RequestBytes.Length);
RequestStream.Close();
HttpWebResponse Resp = (HttpWebResponse)Request.GetResponse();
oReader = new StreamReader(Resp.GetResponseStream(), System.Text.Encoding.Default);
string backstr = oReader.ReadToEnd();
oReader.Close();
Resp.Close();
Doc = XDocument.Parse(backstr);
return Doc;
} 发布于 2012-12-13 06:01:28
如果您重用
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(URL);对象?
连接参数在两次调用之间不会更改。您认为将其设置为静态字段是个好主意吗?
编辑
例如,将Request定义为静态字段:
static HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("http://www.google.com");或者,甚至是一个` `Request对象的字典:
static Dictionary<string,HttpWebRequest> Requests = new Dictionary<string,HttpWebRequest>();然后,在您的SendSMS()方法中:
public XDocument SendSMS()
{
XML = "<message id=\"" + lMessageID + "\"><partnerpassword>" + PartnerPassword + "</partnerpassword><content>" + sMessage + "</content></message>";
URL = "http://sloocetech.net:****/spi-war/spi/" + PartnerID + "/" + sRecipient + "/" + Keyword + "/messages/mt";
//check if the request object exists
if (!Requests.Keys.Contains(sRecipient))
Requests.Add((HttpWebRequest)WebRequest.Create(URL));
//get the existing request from the dictionary
Requests = Requests[sRecipient];
//configure the request
Request.Proxy = null;
RequestBytes = System.Text.Encoding.ASCII.GetBytes(XML);
Request.Method = "POST";
Request.ContentType = "text/xml;charset=utf-8";
Request.ContentLength = RequestBytes.Length;
RequestStream = Request.
RequestStream.Write(RequestBytes, 0, RequestBytes.Length);
RequestStream.Close();
using (System.IO.Stream RequestStream = Request.GetRequestStream())
{
using (WebResponse response = Request.GetResponse())
{
using (oReader = new StreamReader(Resp.GetResponseStream(), System.Text.Encoding.Default))
{
string backstr = oReader.ReadToEnd();
Doc = XDocument.Parse(backstr);
}
}
}
return Doc;
}编辑
也许你也应该使用下面的静态字段:
System.Net.ServicePointManager.DefaultConnectionLimit = 20;发布于 2012-12-13 06:06:22
你正在做的这种忙碌的等待确实消耗了大量的CPU。
while (tasks.Any(t => !t.IsCompleted)) { }实际上,我根本不明白你的代码是如何在没有异常的情况下运行的,因为你先检查计数,然后再排队。但多个线程可能会发现计数为1,并且所有线程都会尝试出队。除了其中一人,其他人都会失败。
我认为你现在应该开始学习多线程的基础知识,然后再继续。任何具体的建议可能都不会有太大帮助,因为代码中充满了错误(除了我提到的两个之外,还有其他的错误)。尝试找到一个关于“使用.net实现fork join并行”的很好的教程,并找出第三方公共关系提供了哪些特性。
重要的是要了解多个线程如何安全地协作,而不会践踏彼此的数据。
发布于 2012-12-13 06:42:57
例如,不要使用Queue,而是使用ConcurrentQueue -有关详细信息,请参阅MSDN。它是一个线程安全的实现,并且大部分是无锁的,因此速度非常快...
https://stackoverflow.com/questions/13849042
复制相似问题