【发布时间】:2017-12-20 12:13:35
【问题描述】:
我遇到了一个小问题。我有一个 BackgroundWorker,它逐行读取文本文件。我想对那些读取的行执行操作,但是这个操作需要一段时间,所以我想我可以为这种工作创建并行运行的任务。到目前为止,这是我的代码:
List<Task> tasks = new List<Task>();
using (StreamReader sr = new StreamReader(this.AppData_Path + this.Playlists_File))
{
string line = "";
while ((line = sr.ReadLine()) != null)
{
if (!string.IsNullOrWhiteSpace(line))
{
Task temp = Task.Factory.StartNew(() => AddSearchPlaylistToList(line));
tasks.Add(temp);
}
if (tasks.Count >= MaxThreads) // MaxThreads = 20
{
Task.WaitAll(tasks.ToArray());
tasks = new List<Task>();
}
}
}
现在这是我的问题开始的地方,出于某种奇怪的原因,多个任务在同一行上工作。在将 BackgroundWorker 中的行提交给 Task 之前,我将其打印出来,看起来像这样:
line1 345893798537598375
line2 435803948508394534
line3 475734573478534879
line4 438348975347895798
line5 234234234234234242
...
当我在 AddSearchPlaylistToList void 中打印 line 参数时,任务正在处理,由于某种原因,它看起来像这样:
line1 345893798537598375
line1 345893798537598375
line2 435803948508394534
line2 435803948508394534
line2 435803948508394534
line3 475734573478534879
...
所以输入似乎搞砸了,但我无法解释原因。
【问题讨论】:
-
这看起来像是应该使用
Parallel.ForEach的情况 -
如果您使用任务,则根本不需要 BGW。这无异于等同于没有
await能力的Task.Run。您也不需要任务列表,或者手动设置线程数 - 这就是 Tasks 和 Task 调度程序的用途。 -
AddSearchPlaylistToList是做什么的?您可能根本不需要任务,或者您可以对其进行修改,使其与任务一起运行得更好。例如,如果它将任何内容附加到列表中,您可以在文件上使用 LINQ 并直接从行中获取结果列表。或者您可以将列表替换为可以由多个线程修改而无需锁定的 ConcurrentQueue -
我会选择@PanagiotisKanavos 提供的
Parallel.ForEach选项。无需重新发明轮子。我是根据经验说话的;)曾经做过同样的事情,当时我不知道这种Parallel的东西已经存在
标签: c# multithreading task