2010-11-19 113 views
1

当前实现:等到parallelCount收集值,使用ThreadPool处理值,等待所有线程完成,重新收集另一组值,等等......C# - 将数据从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();  
} 

我见过显著的性能改进这种方法,但都需要考虑的一些问题:

[1]收集值paramObjects,并且可以避免使用resetEvent的同步,因为线程之间不存在依赖关系(或当前的一组值与下一组值)。我只是这样做来管理对reusableObjects的访问(当一个集合paramObjects完成处理时,我知道可重用对象中的所有对象都是空闲的,所以taskIndex被重置,并且下一组值的每个新任务都将具有其唯一的'可重用对象' 跟...共事)。

[2]在reusableObjects的大小和ThreadPool使用的线程数之间没有真正的连接。我可能初始化reusableObjects有10个对象,并说由于一些限制,ThreadPool只能为我的MultiThreadedGenerate()方法运行3个线程,然后我浪费内存。

因此,通过摆脱paramObjects,怎么能在上面的代码中,一旦一个线程完成了工作的方式加以完善,该线程返回其taskIndex(或reusableObj)它使用和不再需要,使其可用于下一个值。此外,代码应该创建一个reUsableObject并将其添加到一些收集只有当有需求时。在这里使用Queue是一个好主意吗?

谢谢。

+0

你在什么版本的.Net上? – 2010-11-19 17:53:01

+0

我使用.NET 3.5 – alhazen 2010-11-19 17:54:38

回答

5

真的没有理由再做自己的手动线程和任务管理。您可以使用Task Parallel Library(可能为System.Collections.Concurrent进行结果整理)将其重构为更松散耦合的模型。

如果您不需要等待完整的工作,然后将每个Task进行处理,性能可以进一步提高。

TPL出现在.Net 4.0中,但是是back-ported to .Net 3.5。下载here

+0

+1我不知道后端口,所以谢谢你的信息。 – 2010-11-19 18:26:05

+0

@布莱恩 - 我曾经见过这个参考,但之前没有跟踪过它,如果隐藏起来,它非常有用。 – 2010-11-19 18:27:21

相关问题