我试图获得100000字符串输出并尝试使用多个线程但是在检查最终结果字符串时,它只有10000行。
这里=>
string result = "";
private void Testing()
{
var threadA = new Thread(() => { result += A()+Environment.NewLine; });
var threadB = new Thread(() => { result += A() + Environment.NewLine; });
var threadC = new Thread(() => { result += A() + Environment.NewLine; });
var threadD = new Thread(() => { result += A() + Environment.NewLine; });
var threadE = new Thread(() => { result += A() + Environment.NewLine; });
var threadF = new Thread(() => { result += A() + Environment.NewLine; });
var threadG = new Thread(() => { result += A() + Environment.NewLine; });
var threadH = new Thread(() => { result += A() + Environment.NewLine; });
var threadI = new Thread(() => { result += A() + Environment.NewLine; });
var threadJ = new Thread(() => { result += A()+Environment.NewLine; });
threadA.Start();
threadB.Start();
threadC.Start();
threadD.Start();
threadE.Start();
threadF.Start();
threadG.Start();
threadH.Start();
threadI.Start();
threadJ.Start();
threadA.Join();
threadB.Join();
threadC.Join();
threadD.Join();
threadE.Join();
threadF.Join();
threadG.Join();
threadH.Join();
threadI.Join();
threadJ.Join();
}
private string A()
{
for (int i = 0; i <= 10000; i++)
{
result += "select * from testing" + Environment.NewLine;
}
return result;
}
但我没有得到100000,我只得到10000.请让我知道为什么?
答案 0 :(得分:2)
另一种方法是忘记创建线程它有很多开销,并且有许多更好的解决方案。为什么不使用Parallel.For
。它使用线程池,你可以设置你喜欢多少并行度。
此外,如果您正在处理线程,您需要知道如何编写线程安全代码,有许多种锁定机制,或者存在构建时考虑到线程安全性的结构Thread-Safe Collections。如果排序无关紧要,您可以轻松使用ConcurrentBag<T>
哪些可以将您的代码缩短为
static ConcurrentBag<string> results = new ConcurrentBag<string>();
...
private static void myTest(int count )
{
for (var i = 0; i < 1000; i++)
{
results.Add("select * from testing " + i * count);
}
}
<强>用法强>
Parallel.For(0, 10, myTest);
var result = string.Join(Environment.NewLine, results);
无论如何,这并不是解决你的问题或世界上最好的线条编写线程杰作的灵丹妙药,它只是为了向你展示有大量的线程资源和许多方法来做你想要的。
答案 1 :(得分:0)
正如我在评论中解释的那样,A()不是线程安全的。
如果您将result += value;
可视化为result = result+ value;
,您可以看到在获得结果的单个线程和写回结果之间,另一个线程可以获取(现在)旧的价值。
您应该在局部变量中构建每个线程的贡献(我已将其更改为StringBuilder
,因为它比字符串连接更有效)然后同步上下文,并且更新结果对象:
private readonly object _resultLock = new object();
private void A()
{
var lines = new StringBuilder();
for (int i = 0; i <= 10000; i++)
{
lines.AppendLine("select * from testing");
}
lock (_resultLock)
{
result += lines.ToString();
}
}
因为你已经有了一个名为&#34; result&#34;的变量。在课程范围内,我已将A()更改为无效。
最好尽可能少地锁定,因为线程必须等待获取锁定。我们使用_resultLock
以便我们知道锁定是为了。您可以在docs和此question上详细了解lock
。
您可能还想查看任务:docs,Task vs Thread question。