Had*_*adi 1 c# queue multithreading .net-3.5 threadpool
当前实现:等待直到parallelCount
收集值,用于ThreadPool
处理值,等待所有线程完成,重新收集另一组值等等...
码:
private static int parallelCount = 5;
private int taskIndex;
private object[] paramObjects;
// Each ThreadPool thread should access only one item of the array,
// release object when done, to be used by another thread
private object[] reusableObjects = new object[parallelCount];
private void MultiThreadedGenerate(object paramObject)
{
paramObjects[taskIndex] = paramObject;
taskIndex++;
if (taskIndex == parallelCount)
{
MultiThreadedGenerate();
// Reset
taskIndex = 0;
}
}
/*
* Called when 'paramObjects' array gets filled
*/
private void MultiThreadedGenerate()
{
int remainingToGenerate = paramObjects.Count;
resetEvent.Reset();
for (int i = 0; i < paramObjects.Count; i++)
{
ThreadPool.QueueUserWorkItem(delegate(object obj)
{
try
{
int currentIndex = (int) obj;
Generate(currentIndex, paramObjects[currentIndex], reusableObjects[currentIndex]);
}
finally
{
if (Interlocked.Decrement(ref remainingToGenerate) == 0)
{
resetEvent.Set();
}
}
}, i);
}
resetEvent.WaitOne();
}
Run Code Online (Sandbox Code Playgroud)
我已经看到使用这种方法可以显着改善性能,但是需要考虑许多问题:
[1] 可以避免收集值paramObjects
和同步使用resetEvent
,因为线程之间没有依赖关系(或者当前值集与下一组值之间).我只是这样做来管理访问权限reusableObjects
(当一个集合paramObjects
完成处理时,我知道reusableObjects中的所有对象都是空闲的,因此taskIndex
重置并且下一组值的每个新任务都将具有其唯一的'reusableObj'工作用).
[2]使用的大小reusableObjects
和线程数之间没有真正的联系ThreadPool
.我可能初始化reusableObjects
有10个对象,并说由于一些限制,ThreadPool只能为我的MultiThreadedGenerate()
方法运行3个线程,然后我浪费内存.
因此,通过去除paramObjects
,如何以一种线程完成其作业的方式改进上述代码,该线程返回它所使用的taskIndex
(或者reusableObj
)它不再需要使得它可用于下一个值.此外,代码应该创建一个reUsableObject
并仅在有需求时将其添加到某个集合.在这里使用Queue是一个好主意吗?
谢谢.
实际上没有理由再进行自己的手动线程和任务管理了.您可以使用任务并行库(以及可能的System.Collections.Concurrent进行结果整理)将其重构为更松散耦合的模型.
如果您不需要等待完整的工作再Task
进行处理,那么性能可以进一步提高.
TPL出现在.Net 4.0中,但后端移植到.Net 3.5.在这里下载.