gpt4 book ai didi

c# - 在 Foreach 中创建和启动任务

转载 作者:行者123 更新时间:2023-11-30 17:40:12 26 4
gpt4 key购买 nike

我试图从网站上抓取一些数据。这是我的类(class):

class ClosureCraziness
{
public string SaveFolder { get; set; }

public void Save(Dictionary<string, string> idToWebLocation)
{
var tasks = new List<Task>();
foreach (var kvp in idToWebLocation)
{
var task = new Task(() => Download(kvp.Key, kvp.Value));
task.Start();
tasks.Add(task);
}

Task.WaitAll(tasks.ToArray());
}

void Download(string id, string location)
{
var filename = $"{id}.html";
string source = string.Empty;
try
{
source = GetSource(location);
}
catch (Exception e)
{
// handle exception
}

var path = Path.Combine(SaveFolder, filename);
using (var sw = new StreamWriter(path))
sw.Write(source);
}

string GetSource(string location)
{
using (var client = new WebClient())
{
return client.DownloadString(location);
}
}
}

当我执行时,我会得到类似下面的结果。您会注意到文件的内容(下载的源)与名称不匹配:

磁盘上的文件名 | File Contents

apple.html <html> apple </html>

orange.html <html> orange </html>

pear.html <html> peach </html>

peach.html <html> peach </html>

葡萄.html <html> apple </html>

plum.html <html> plum </html>

(我不知道如何很好地格式化它)

起初我很困惑,因为磁盘上的文件名是正确的,而且我确定我的 Dictionary<string, string>格式正确(我检查了 6 次,所有不同的方式),这意味着 Id 与 Web 位置的关联很好。

我想这可能是一个关闭问题,记忆起 Eric Lippert schooling me on the implementation of foreach .所以我尝试了:

public void Save(Dictionary<string, string> idToWebLocation)
{
var tasks = new List<Task>();
foreach (var kvp in idToWebLocation)
{
var innerKvp = kvp;
var task = new Task(() => Download(innerKvp.Key, innerKvp.Value));
task.Start();
tasks.Add(task);
}

Task.WaitAll(tasks.ToArray());
}

并且,为了安全起见:

public void Save(Dictionary<string, string> idToWebLocation)
{
var tasks = new List<Task>();
foreach (var kvp in idToWebLocation)
{
var innerKvp = kvp;
var id = innerKvp.Key;
var loc = innerKvp.Value;
var task = new Task(() => Download(id, loc));
task.Start();
tasks.Add(task);
}

Task.WaitAll(tasks.ToArray());
}

另外,因为谁知道呢:

public void Save(Dictionary<string, string> idToWebLocation)
{
var tasks = new List<Task>();
foreach (var kvp in idToWebLocation)
{
var innerKvp = kvp;
var task = new Task(() =>
{
var id = innerKvp.Key;
var loc = innerKvp.Value;
Download(id, loc);
});

task.Start();
tasks.Add(task);
}

Task.WaitAll(tasks.ToArray());
}

但是这些都不起作用。显然,我对这段代码的编译方式缺乏了解,但我的意思是,这到底是怎么回事。

似乎介于 var filename = $"{id}.html"; 之间和 source = GetSource(location);location在改变。我很确定代码是线程安全的,没有共享状态,对吧?

但显然不是,因为当我同步遍历字典时,一切都按预期工作。

也许我在这里遗漏了一些关于外壳、线程、内存或其他方面的基本要点。我不知道,但我的办公 table 上满是头发,而且我快要秃顶了。

最佳答案

任务并行库有一个 for each 方法,非常适合您正在做的事情。您可能会发现这与您当前正在尝试做的事情很有趣/相关:

https://msdn.microsoft.com/en-us/library/dd460720(v=vs.110).aspx

关于c# - 在 Foreach 中创建和启动任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34536679/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com