让我们说我想要做的就是验证一百万个字符串,每次验证都需要几秒钟。
我的方法:
我有一个这样声明的线程数组:
Thread[] workers = new Thread[50];
我没有数组中的所有字符串,它们通过一些计算,然后我在启动进程时没有所有字符串,但我有一个方法返回下一个:
public string next()
{
//my code
}
我已经能够像这样运行所有50个线程:
for (int x = 0; x < 50; x++)
{
workers[x] = new Thread(new ParameterizedThreadStart(myMethod));
workers[x].Start(next());
}
快速启动所有50个线程“同时”然后我的日志(由myMethod提供)几乎同时获得50个响应(1~1.5秒)
如何考虑到Thread类没有暴露任何事件或任何类似事件,如何让每个刚刚完成的线程再次使用下一个字符串运行?
注意:我已经完成了一些性能测试,我更喜欢使用常规线程而不是BackgroundWorkers。
在.net 3.5中使用C#。
答案 0 :(得分:5)
听起来你应该使用ThreadPool。然后你可以这样做:
while(MoreWorkIsAvailable)
{
string nextString = next();
ThreadPool.QueueUserWorkItem(new WaitCallback(myMethod), nextString);
}
线程池甚至允许您在最大线程数上设置一个硬帽,以允许通过SetMaxThreads一次运行。
答案 1 :(得分:2)
您无法通过线程系统获取事件。您可以等待Thread.Join
的单个线程,但是您不能等待任何线程并获得首先完成的线程。最好的方法是在每个线程中放置一个while循环来轮询工作项队列,直到队列为空。
答案 2 :(得分:1)
您可以像ADO.NET或枚举一样使用next()方法。保持返回值直到它完成,然后返回null。让你的线程在while循环中使用该方法,直到方法返回null,然后退出。
为了澄清,你需要做一些背景工作。你必须使你的next()方法是线程安全的,所以你总是返回下一个没有重复的值。您还必须将引用传递给对象而不是next()方法的输出。线程安全部分是关于它的唯一真正复杂的事情,它只是意味着你必须锁定next()方法的一部分:
状态稳定后,您可以释放锁定,下一个线程可以使其字符串工作。
编辑:这可能仍然是要走的路,尽管为了简单起见我喜欢ThreadPool方法。在这种情况下,代码将类似于:
YourStringGenerator generator;
//instatiate generator
for (int x = 0; x < 50; x++)
{
workers[x] = new Thread(new ParameterizedThreadStart(myMethod));
workers[x].Start(generator);
}
然后
myMethod(YourStringGenerator generator)
{
String compare;
while((compare=generator.next())!=null)
{
//do comparison, etc.
}
return;
}
next()看起来像
String next()
{
lock(this.index) //see msdn for info. Link below.
{
//determine next string
//update index
}
//generate or get next string from list and return it
//or if empty, return null
}
答案 3 :(得分:1)
添加到您的线程方法,不仅处理一个数据,而且处理“下一个无人认领”的数据。
您希望围绕枚举器的MoveNext进行一些同步,并获取对Current的引用的副本。没有两个线程可以推进枚举器并同时抓取项目。然后,在获得引用后,释放同步锁并进行验证。
您可能还想查看Microsoft的Px并行扩展以利用多个CPU(内核?)。我没有使用它,但如果你的验证是纯粹的算法(而不是对数据库进行检查),那么多处理器参与是击败单线程模型的唯一方法。