C# 与任务并行,有些任务有效,有些任务无效
我有一个网站,我写了一个HttpModule来转换所有链接,所以一切都很好,直到我要在转换URL中使用并行性 这是我的测试控制台应用程序:C# 与任务并行,有些任务有效,有些任务无效,c#,.net,parallel-processing,task-parallel-library,C#,.net,Parallel Processing,Task Parallel Library,我有一个网站,我写了一个HttpModule来转换所有链接,所以一切都很好,直到我要在转换URL中使用并行性 这是我的测试控制台应用程序: class Program { static void Main(string[] args) { new Job().Do(); } } public class Job { public void Do() {
class Program
{
static void Main(string[] args)
{
new Job().Do();
}
}
public class Job
{
public void Do()
{
string content = @"
new link1 href=""www.yahoo1.com"" end
new link2 href=""www.yahoo2.com"" end
new link3 href=""www.yahoo3.com"" end
new link4 href=""www.yahoo4.com"" end
new link5 href=""www.yahoo5.com"" end
new link6 href=""www.yahoo6.com"" end
";
string newcontent = Transformlink(content);
Console.WriteLine(content);
Console.WriteLine();
Console.WriteLine(newcontent);
Console.ReadLine();
}
private string Transformlink(string content)
{
List<UrlIndex> AllUrls = GetUrls(content);
List<Task> TaskPool = new List<Task>();
foreach (UrlIndex Item in AllUrls)
TaskPool.Add(Task.Factory.StartNew(() => TransformUrl(Item)));
Task.WaitAll(TaskPool.ToArray());
return ReplaceUrlWithTransformUrl(content, AllUrls);
}
private string ReplaceUrlWithTransformUrl(string content, List<UrlIndex> AllUrls)
{
for (int i = AllUrls.Count - 1; i >= 0; i--)
{
UrlIndex CurrentItem = AllUrls[i];
content = content.Substring(0, CurrentItem.StartIndex) + CurrentItem.TransformedUrl + content.Substring(CurrentItem.EndIndex);
}
return content;
}
private void TransformUrl(UrlIndex urlindex)
{
urlindex.TransformedUrl = string.Format("Google{0}.com", new Random().Next(100, 999).ToString());
}
private List<UrlIndex> GetUrls(string content)
{
//Get Start And End Index, Get Url Set TransformedUrl = Url
List<UrlIndex> AllUrls = new List<UrlIndex>();
int startindex = 0;
int endIndex = 0;
int previousindex = 0;
while (startindex != -1)
{
startindex = content.IndexOf("href=\"", previousindex);
if (startindex == -1)
break;
startindex += 6;
previousindex = startindex;
endIndex = content.IndexOf("\"", previousindex);
if (endIndex == -1)
break;
previousindex = endIndex;
string url = content.Substring(startindex, endIndex - startindex);
AllUrls.Add(new UrlIndex() { StartIndex = startindex, EndIndex = endIndex, Url = url, TransformedUrl = url });
}
return AllUrls;
}
}
public class UrlIndex
{
public int StartIndex { get; set; }
public int EndIndex { get; set; }
public string Url { get; set; }
public string TransformedUrl { get; set; }
}
这正是我想要的
但结果是:
new link1 href=""www.yahoo1.com"" end
new link2 href=""www.yahoo2.com"" end
new link3 href=""www.yahoo3.com"" end
new link4 href=""www.yahoo4.com"" end
new link5 href=""www.yahoo5.com"" end
new link6 href=""www.Google125.com"" end
正如您所看到的,最后一个链接已转换。在某些情况下:
new link1 href=""www.yahoo1.com"" end
new link2 href=""www.yahoo2.com"" end
new link3 href=""www.Google285.com"" end
new link4 href=""www.yahoo4.com"" end
new link5 href=""www.yahoo5.com"" end
new link6 href=""www.Google125.com"" end
控制台项目位于.NET4中
这是我的错吗?为什么所有任务都不起作用?Task.WaitAllTaskPool.ToArray的行;这还不够吗?有什么建议吗 看起来像是一个关闭问题。 更改Transformlink方法,如下所示:
private string Transformlink(string content)
{
List<UrlIndex> AllUrls = GetUrls(content);
List<Task> TaskPool = new List<Task>();
foreach (UrlIndex Item in AllUrls)
{
val localItem = Item;
TaskPool.Add(Task.Factory.StartNew(() => TransformUrl(localItem)));
}
Task.WaitAll(TaskPool.ToArray());
return ReplaceUrlWithTransformUrl(content, AllUrls);
}
编辑/解释:
这是由安排任务的方式造成的。你没有真正的方法来控制它。在您的控件中,应用程序任务的执行安排得足够快,可以在循环迭代之前完成。因为您在TransformUrl中传递的项目变量仍然是您考虑的那个
但在服务器应用程序中,循环在执行任何任务之前完成。
请注意,您传递了一个引用。该引用在每次迭代中都会更改。所以,在循环完成后,所有任务都将在同一个URLDINDEX实例上执行转换。这就是发生的事情。
通过创建局部变量,可以存储对要使用的实际对象的引用
因此,使用局部变量是正确的方法。它在控制台应用程序中工作,因为时间条件正确,我称之为运气:在这种情况下,使用Task可能更好。ParallelFor@AlexOvechkin我比较并行。但是并行的持续时间。在这种情况下,并行的持续时间比当前的时间长code@Saeid,并行。如果您有大量数据,而不是10个链接,则会更高效,所以这取决于你的input@AlexOvechkin谢谢亚历克斯,我发现这一点:同意你的评论
private string Transformlink(string content)
{
List<UrlIndex> AllUrls = GetUrls(content);
List<Task> TaskPool = new List<Task>();
foreach (UrlIndex Item in AllUrls)
{
val localItem = Item;
TaskPool.Add(Task.Factory.StartNew(() => TransformUrl(localItem)));
}
Task.WaitAll(TaskPool.ToArray());
return ReplaceUrlWithTransformUrl(content, AllUrls);
}