我正在开发一个 C# winforms 应用程序,我有大约 84 个 url,我想使用 html 敏捷包解析它们
对于 84 条记录,使用以下代码完成作业需要 150 秒。
我想知道我有什么选择可以让它运行得更快? 任何帮助都非常感谢!
以下是我完成这项工作的代码结构
public class URL_DATA
{
public string URL { get; set; }
public HtmlDocument doc { get; set; }
}
then I call the below function to do the job
public async Task ProcessUrls(string cookie)
{
var tsk = new List<Task>();
//UrlsToProcess is List<URL_DATA>
UrlsToProcess.ForEach(async data =>
{
tsk.Add(Task.Run(async () =>
{
var htmToParse = await ScrapUtils.GetAgilityDocby(cookie, data.URL);
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(htmToParse);
data.doc = htmlDoc;
}));
});
await Task.WhenAll(tsk).ConfigureAwait(false);
}
最后是我用来获取请求字符串的方法。
public static async Task<string> GetAgilityDocby(string cookie, string url)
{
using (var wc = new WebClient())
{
wc.Proxy = null;// WebRequest.DefaultWebProxy;// GlobalProxySelection.GetEmptyWebProxy();
wc.Headers.Add(HttpRequestHeader.Cookie, cookie);
wc.Headers.Add(HttpRequestHeader.UserAgent,
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36");
wc.Encoding = Encoding.UTF8;
test++;
return await wc.DownloadStringTaskAsync(url).ConfigureAwait(false);
}
}
您正在使用具有异步 lambda 的ForEach
。我怀疑它会使您的代码按顺序运行而不是并行运行,因为每次下一次迭代都会等待。
所以你可以做些什么来确定这一点:
- 检查一个 URL 的操作的最长时间,该时间应该大约是整个事情应该有多快(如果您有足够的带宽、内存和 CPU(。
- 验证操作是否确实并行运行。例如,通过将计数器输出到控制台。它不应该是连续的,看起来足够随机
您可以将任务创建代码更改为此代码,例如尝试:
var allTasks = myUrls.Select(url => Task.Run(() => {yourCode})
Task.WhenAll(allTasks);
尝试将最小运行线程数增加
ThreadPool.SetMinThreads(84,84);
这应该会加快速度。
至于 Ilya 指出的任务创建,我会评论您完全省略 Task.Run/AwaitAll 部分并使用并行机制,该机制正是针对此类问题开发的:
Parallel.ForEach(UrlsToProcess, data =>
{
var htmToParse = ScrapUtils.GetAgilityDocby(cookie, data.URL);
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(htmToParse);
data.doc = htmlDoc;
});