Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 任务的并行处理<;T>;物体_C#_Recursion_Parallel Processing_Task Parallel Library_Task - Fatal编程技术网

C# 任务的并行处理<;T>;物体

C# 任务的并行处理<;T>;物体,c#,recursion,parallel-processing,task-parallel-library,task,C#,Recursion,Parallel Processing,Task Parallel Library,Task,我从原始URL开始抓取网页,并递归地跟踪任何链接,以确定这些网页上列出的电子邮件地址。我使用VS2015和.NET4.6来利用线程上提供的抽象/简单任务 我让页面下载以递归方式运行,但应用程序似乎仍然存在严重的瓶颈。使用下面的简单代码,如何使流程能够更并行地处理每个网页,以查询电子邮件内容和后续url链接 似乎任务可以同时启动,这样页面上的所有URL都可以同时添加到循环逻辑的下一次迭代中?或者任务现在可以在引擎盖下处理这个问题吗 下面是我的代码,请提供一些解释,以便我能够更好地理解解决方案,因为

我从原始URL开始抓取网页,并递归地跟踪任何链接,以确定这些网页上列出的电子邮件地址。我使用VS2015和.NET4.6来利用线程上提供的抽象/简单任务

我让页面下载以递归方式运行,但应用程序似乎仍然存在严重的瓶颈。使用下面的简单代码,如何使流程能够更并行地处理每个网页,以查询电子邮件内容和后续url链接

似乎任务可以同时启动,这样页面上的所有URL都可以同时添加到循环逻辑的下一次迭代中?或者任务现在可以在引擎盖下处理这个问题吗

下面是我的代码,请提供一些解释,以便我能够更好地理解解决方案,因为我刚刚开始执行任务。(代码正在使用HTML敏捷包)

List lstEmailData=newlist();
私有无效开始按钮单击(对象发送者,路由目标)
{
getWEbData(“http://localhost:801/“”;//起始url
}
私有异步void getWEbData(字符串url){
Task getHTMLTask=AccessTheWebAsync(url);
string PageData=await getHTMLTask;
var html=新的HtmlDocument();
html.LoadHtml(页面数据);
var emails=html.DocumentNode.SelectNodes(“//a[@href]”)
.选择(a=>a.Attributes[“href”].Value)
.Where(href=>href.StartsWith(“mailto:”)//保留电子邮件,跳过链接
.ToList();
添加(新页面电子邮件(url,电子邮件));
var url=html.DocumentNode.SelectNodes(“//a[@href]”)
.选择(a=>a.Attributes[“href”].Value)
.Where(href=>!href.StartsWith(“mailto:”)//跳过电子邮件,只查找url链接
.ToList();
foreach(URL中的字符串s){
获取网络数据;
}
}
异步任务访问WebAsync(字符串URL)
{
HttpClient客户端=新HttpClient(){MaxResponseContentBufferSize=1000000};
任务getStringTask=client.GetStringAsync(URL);
返回等待getStringTask;
}

核心问题可能是您受到远程服务器的限制,而您无法控制远程服务器。还有一种可能性是,您可能会受到.NET中(旧的)默认连接限制的限制;在流程开始时,尝试将
ServicePointManager.DefaultConnectionLimit
设置为
int.MaxValue
。除此之外,你无能为力

由于您正在学习
async
,您应该知道最好避免
async void
。理想情况下,
getWEbData
应该返回一个
Task
,此更改允许您将“子”URL视为“子”任务。这对于正确传播错误特别有用:

private async void startButton_Click(object sender, RoutedEventArgs e)
{
  await GetWebDataAsync("http://localhost:801/"); //starting url
}

private async Task GetWebDataAsync(string url) {
  var urls = ...;

  var urlTasks = urls.Select(s => GetWebDataAsync(s));
  await Task.WhenAll(urlTasks);
}

你能升级到.NET 4.5吗?或者至少是.NET4.0?有更新的技术和库可用,这将是一个很大的帮助,但他们只支持更新的平台。我使用的是visual studio 2015和.net 4.6。当然,您可以将foreach循环更改为并行结构来提供帮助,但服务器允许您同时发出的请求数量通常会受到限制,因此您不会看到您希望的速度。PS处理此问题的更好方法是使用URL队列进行访问,例如@kacalapy您的代码中有多个问题。首先,也是最重要的一点,您正在引入竞争条件lstmaildata.Add(newpageemail(url,emails));由于列表不是线程安全的,所以必须改用ConcurrentBag之类的东西。第二个问题是,您在阻塞场景中链接一些任务,访问WebAsync是异步的(因此实现为Task)并等待它,但在已经等待Task result的方法中,只会浪费资源。第三个问题是,您无法检测到算法的完成情况,实际上,它可以永远存在…@IanMercer foreach正在调用异步方法,应该是并行的…谢谢,这有助于避免错误,但实际上不允许getWEbData(newURL)的多个异步操作串联运行所有单独的线程。我相信这是在最短的时间内处理许多网页的最终设计。我的逻辑似乎是顺序的,我希望它更并行。@kacalapy:它是并发的,但不是并行的。多线程是不必要的,因为它们是I/O绑定的操作。此代码将发送无限数量的同时请求,仅受硬件、带宽和服务器端限制。
private async void startButton_Click(object sender, RoutedEventArgs e)
{
  await GetWebDataAsync("http://localhost:801/"); //starting url
}

private async Task GetWebDataAsync(string url) {
  var urls = ...;

  var urlTasks = urls.Select(s => GetWebDataAsync(s));
  await Task.WhenAll(urlTasks);
}