我正在尝试多线程httpwebrequest。它不需要返回响应,我只需要尽快发送它们。目前我正在使用任务,但显然这不是最有效的处理方式,因为它使用您的系统规范来确定线程而不是连接速度。
所以我想我想问的是,根据连接速度而不是PC的内核数量,使用线程的最有效方法是什么。
由于
答案 0 :(得分:6)
您可以使用BeginGetResponse()
方法async
WebRequest
方法。
答案 1 :(得分:3)
默认情况下,允许.Net应用程序打开2个与Web服务器的连接。您可以通过设置此变量来增加数量
//Set the connection limit of HTTP
System.Net.ServicePointManager.DefaultConnectionLimit = 20;
使用常规调用或异步方法,使用HttpWebRequest / HttpWebResponse,必须从GetReponseStream()正确处理/关闭Stream。通过从GetResponseStream()关闭Stream,您的应用程序将在完成后终止HTTP连接。
例如,在下面的代码中,我从Web返回StreamReader
public static StreamReader LoadWeb(string URL)
{
if (!URL.StartsWith("http"))
{
URL = "http://" + URL;
}
HttpWebResponse myResponse = null;
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(new Uri(URL));
System.IO.Stream myStream = null;
StreamReader myStreamReader = null;
myRequest.Method = "GET";
myRequest.Proxy = null;
myRequest.Timeout = 60000;
myRequest.KeepAlive = false;
try
{
myResponse = (HttpWebResponse)myRequest.GetResponse();
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("Error : " + ex.Message);
return null;
}
if (myResponse != null)
{
if (myResponse.StatusCode == System.Net.HttpStatusCode.OK)
{
myStream = myResponse.GetResponseStream();
myStreamReader = new StreamReader(myStream);
}
}
return myStreamReader;
}
之后,我从LoadWeb函数返回
StreamReader reader = LoadWeb("http://www.google.com");
//...process the reader
//Finally, close the reader
if (reader != null)
reader.Close(); //This line will terminate the HTTP connection
希望它有所帮助。
答案 2 :(得分:1)
我建议您构建一个工作队列,并在字典中跟踪正在运行的工作程序,并在运行完成后启动新工作程序。这使您可以调整活动工作人员的数量。它还为您提供了一组活跃的工作人员,以防您需要发送停止消息。
您需要将此添加到app.config以超过默认连接限制2:
<system.net>
<connectionManagement>
<remove address="*"/>
<add address="*" maxconnection="10" />
</connectionManagement>
</system.net>
在下面的示例中,我使用回调从队列中删除一个worker,并使用Monitor
来清空等待的worker队列的清空。
using System;
using System.Collections.Generic;
using System.Threading;
namespace Demo
{
class Program
{
static Queue<Worker> waitingWorkers = new Queue<Worker>();
static Dictionary<int, Worker> activeWorkers = new Dictionary<int, Worker>();
static int maxThreads = 10;
static object waitLock = new object();
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
waitingWorkers.Enqueue(new Worker(new WorkerDoneDelegate(WorkerDone)));
}
lock (waitLock)
{
while (waitingWorkers.Count > 0)
{
if (activeWorkers.Count > maxThreads)
{
Monitor.Wait(waitLock);
}
Worker worker = waitingWorkers.Dequeue();
Thread thread = new Thread(worker.SendSomething);
thread.IsBackground = true;
activeWorkers[thread.ManagedThreadId] = worker;
thread.Start();
}
}
Console.WriteLine("Queue empty");
Console.ReadKey();
}
static void WorkerDone()
{
lock (waitLock)
{
activeWorkers.Remove(Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("Worker done - id=" + Thread.CurrentThread.ManagedThreadId.ToString());
Monitor.Pulse(waitLock);
}
}
public delegate void WorkerDoneDelegate();
public class Worker
{
static Random rnd = new Random();
WorkerDoneDelegate Done;
public Worker(WorkerDoneDelegate workerDoneArg)
{
Done = workerDoneArg;
}
public void SendSomething()
{
Console.WriteLine("Worker send - id=" + Thread.CurrentThread.ManagedThreadId.ToString());
Thread.Sleep(rnd.Next(1, 1000));
Done();
}
}
}
}
答案 3 :(得分:0)
或者只是使用Parallel.For / ForEach它会为你做线程优化(选择池大小,线程数等等)。)