次のプロセスを並列化するために、基本的に並列の方法で反復する関数があります。
- ウェブページを取得する
- HTML コードを解析する
- 結果を返し、結果コレクションに追加する
問題は、最初の実行に約 5 分、2 回目の実行に約 40 分かかることです。入力コレクションは変更されていないため、実行時間はほぼ同じです。何か案が?
GetPrices(int) を含めました。これが 2 回目に実行されると、netstat で 0 接続から開始されます (したがって、最初に使用可能な接続を使い果たすことはありません) が、5 接続までしか増加しません (最初の実行では 30 でした)。
また、返品コレクションをロックする必要があると思いますか?
public Dictionary<int, Dictionary<int, double>> GetPrices(List<int> IDs)
{
Stopwatch web_time = new Stopwatch(), regex_time = new Stopwatch();
Dictionary<int, Dictionary<int, double>> ret = new Dictionary<int, Dictionary<int, double>>();
int aux_bkp = ServicePointManager.DefaultConnectionLimit;
ParallelOptions pOptions = new ParallelOptions();
ServicePointManager.DefaultConnectionLimit = 30;
pOptions.MaxDegreeOfParallelism = 35;
Parallel.ForEach(IDs, pOptions, ID=>
{
Dictionary<int, double> aux = GetPrices(ID);
lock (ret)
{
ret.Add(ID, new Dictionary<int, double>());
foreach (int kID in aux.Keys)
{
ret[mktID].Add(kID , aux[kID ]);
}
}
});
ServicePointManager.DefaultConnectionLimit = aux_bkp;
return ret;
}
public static Dictionary<int, double> GetPrices(int ID)
{
Stopwatch web_time = new Stopwatch(), regex_time = new Stopwatch();
WebClient webclient = new WebClient();
string resp;
Dictionary<int, double> ret = new Dictionary<int, double>();
bool success = false;
int retries = 0;
web_time.Start();
while (!success)
try
{
Debug.WriteLine(string.Format("Get HTML: ({1}) - ({0})", url, ID));
resp = webclient.DownloadString(url);
success = true;
web_time.Stop();
regex_time.Start();
regex_time.Start();
ret = ProcessHTML(resp, ID);
regex_time.Stop();
}
catch (WebException e)
{
System.Net.HttpWebResponse aux;
aux = e.Response as System.Net.HttpWebResponse;
if (aux == null || aux.StatusCode != HttpStatusCode.NotFound)
{
success = false;
retries++;
System.Threading.Thread.Sleep(new System.Random().Next(5000));
System.Diagnostics.Debug.WriteLine("HTTP Error - " + e.ToString());
}
else if (aux != null || aux.StatusCode == HttpStatusCode.NotFound)
{
success = true;
}
}
regex_time.Stop();
return ret;
}