我正在尝试制作一个工具,从我提供的许多 URL 中获取源字符串。我将这段代码用于多线程
new Thread(() =>
{
while (stop != true)
{
if (nowworker >= threads)
{
Thread.Sleep(50);
}
else
{
if (i <= urllist.Count - 1)
{
var thread = new Thread(() =>
{
string source = GetSource(urllist[i]);
SaveToFile(source, i + ".txt");
});
thread.Start();
i++;
nowworker += 1;
}
else
{
stop = true;
}
}
}
}).Start();
它运行非常顺利,直到我检查结果并且有一些重复的结果并且缺少我提供的一些 url 如果对许多 url 使用更少的线程(10 线程 - 20 url)但是当对 20 url 使用 20 线程时没有问题。
请帮帮我。谢谢。
最佳答案
if (i <= urllist.Count - 1)
{
var thread = new Thread(() =>
{
string source = GetSource(urllist[i]);
SaveToFile(source, i + ".txt");
});
thread.Start();
i++;
nowworker += 1;
}
您传递给线程的方法不能保证在 i
更新(i++
)之前执行。事实上,不太可能。这意味着多个线程可能使用相同的 i
值,而 i
的某些值不会有任何线程执行它。
更糟糕的是,GetSource
可能使用与 SaveToFile
不同的 i
值。
在这里阅读:http://jonskeet.uk/csharp/csharp2/delegates.html
这将解决它:
if (i <= urllist.Count - 1)
{
var currentIndex = i;
var thread = new Thread(() =>
{
string source = GetSource(urllist[currentIndex]);
SaveToFile(source, currentIndex + ".txt");
});
thread.Start();
i++;
nowworker += 1;
}
更好的是,您可以将整个代码块替换为:
Parallel.For(0, urlList.Count - 1,
new ParallelOptions { MaxDegreeOfParallelism = threads },
i =>
{
string source = GetSource(urllist[i]);
SaveToFile(source, i + ".txt");
}
);
这将摆脱代码臭味 Thread.Sleep()
并让 .NET 为您管理旋转线程
关于C#多线程重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32643451/