ボトルネックはインターネット接続であるため、それほど高速化することはできません。ただし、できることがあります。
1) LINQ で行数をカウントしないでください。これは配列であり、そのサイズはわかっています (マイクロ最適化、この変更に気付くことはありません)。
2)using
使い捨てオブジェクトを解放するために使用します(速度、より良いエラー処理とは関係ありません。コードに問題が発生した場合、GCでリソースを解放します)。
3) 平行にする。これにより、物事が少しスピードアップします。
private void button4_Click(object sender, EventArgs e)
{
var lines = File.ReadAllLines(@"c:\data\temp.txt");
var options = new ParallelOptions { MaxDegreeOfParallelism = 4 };
Parallel.ForEach(lines, options, line =>
{
var request = WebRequest.Create(line);
using (var response = request.GetResponse())
{
var reader = new StreamReader(response.GetResponseStream(), Encoding.ASCII);
// Do your stuff
BeginInvoke(new MethodInvoker(delegate
{
textBox1.Text += ".";
}));
}
});
}
さらにいくつかのメモ:
より完全な例にするために、クリック イベント ハンドラーは次のようになります。
private void button4_Click(object sender, EventArgs e)
{
var options = new ParallelOptions { MaxDegreeOfParallelism = 4 };
Parallel.ForEach(ReadUrlList(@"c:\data\temp.txt"), options, ProcessUrl);
}
各 URL を処理し、URL リストを読み取る実際のコード:
private static string[] ReadUrlList(string path)
{
return File.ReadAllLines(@"c:\data\temp.txt");
}
private void ProcessUrl(string url)
{
ProcessResponse(response =>
{
using (var reader = new StreamReader(response.GetResponseStream(), Encoding.ASCII))
{
// Do your stuff
// We're working on separate threads, to access UI we
// have to dispatch the call to UI thread. Note that
// code will be executed asynchronously then local
// objects may have been disposed!
BeginInvoke(new MethodInvoker(delegate
{
textBox1.Text += ".";
}));
}
});
}
このヘルパー メソッドを使用して、ネットワーク操作の試行/待機パターンを非表示にします。
private static void ProcessResponse(string url, Action<WebResponse> action)
{
for (int i=1; i <= NumberOfRetries; ++i)
{
try
{
var request = WebRequest.Create(line);
using (var response = request.GetResponse())
{
action(response);
}
break;
}
catch (Exception e)
{
if (i == NumberOfRetries)
throw;
Thread.Sleep(DelayOnRetry);
}
}
}
private const int NumberOfRetries = 3;
private const int DelayOnRetry = 1000;