我正在嘗試多線程httpwebrequest。它不需要返回響應,我只需要儘快發送它們。目前我正在使用任務,但顯然這不是最有效的做事方式,因爲它使用您的系統規格來確定線程而不是連接速度。如何高效地多線程HttpWebRequests?
所以我想我想問什麼是使用基於連接速度的線程而不是您的PC的核心數量的最有效的方式。
感謝
我正在嘗試多線程httpwebrequest。它不需要返回響應,我只需要儘快發送它們。目前我正在使用任務,但顯然這不是最有效的做事方式,因爲它使用您的系統規格來確定線程而不是連接速度。如何高效地多線程HttpWebRequests?
所以我想我想問什麼是使用基於連接速度的線程而不是您的PC的核心數量的最有效的方式。
感謝
您可以使用BeginGetResponse()
方法這是WebRequest
一個async
方法。
我建議你建立一個工作隊伍,跟蹤字典中運行的工作人員,啓動新的工作人員作爲跑完工。這可讓您調整活動工作人員的人數。它還會爲您提供一組活動工作人員,以便您需要向他們發送停止消息。
你需要添加到您的app.config讓過去的兩個默認的連接限制:
<system.net>
<connectionManagement>
<remove address="*"/>
<add address="*" maxconnection="10" />
</connectionManagement>
</system.net>
在下面的例子中,我使用回調從隊列和刪除工作者Monitor
來關閉等待工作隊列的清空。
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();
}
}
}
}
或者乾脆使用的Parallel.For /的ForEach它會做的線程優化(選擇池大小,線程數,等等,等等。)爲您:)
默認情況下,.NET應用程序是允許打開2個連接到Web服務器。您可以通過使用常規的調用或異步方法,用的HttpWebRequest/HttpWebResponse設置此變量
//Set the connection limit of HTTP
System.Net.ServicePointManager.DefaultConnectionLimit = 20;
或者增加數量,必須妥善處置/關閉從GetReponseStream()的流。通過從GetResponseStream()關閉Stream,你的應用程序將在完成後終止HTTP連接。
例如,在下面的代碼,我從網上
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;
}
後返回StreamReader的,我從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
希望它可以幫助的回報。
反正這不是多線程。 – user2913184 2018-02-12 21:44:05
第二@Asif的回答,異步I/O可能比創建更多的線程更有效。 – 2012-07-12 17:09:29