简体   繁体   English

C#-将数据从ThreadPool线程传递回主线程

[英]C# - Pass data back from ThreadPool thread to main thread

Current implementation: Waits until parallelCount values are collected, uses ThreadPool to process the values, waits until all threads complete, re-collect another set of values and so on... 当前实现:等待直到收集parallelCount值,使用ThreadPool处理值,等待直到所有线程完成,重新收集另一组值,依此类推...

Code: 码:

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();    
}

I've seen significant performance improvements with this approach, however there are a number of issues to consider: 我已经看到这种方法可以显着提高性能,但是有许多问题需要考虑:

[1] Collecting values in paramObjects and synchronization using resetEvent can be avoided as there is no dependency between the threads (or current set of values with the next set of values). [1]可以避免在paramObjects收集值以及使用resetEvent进行同步,因为线程之间(或当前值集与下一组值)之间没有依赖性。 I'm only doing this to manage access to reusableObjects (when a set paramObjects is done processing, I know that all objects in reusableObjects are free, so taskIndex is reset and each new task of the next set of values will have its unique 'reusableObj' to work with). 我只是这样做来管理对reusableObjects访问(当完成对paramObjects的处理时,我知道reusableObjects中的所有对象都是空闲的,因此将taskIndex重置,并且下一组值的每个新任务将具有其唯一的'reusableObj ' 跟...共事)。

[2] There is no real connection between the size of reusableObjects and the number of threads the ThreadPool uses. [2]在reusableObjects的大小和ThreadPool使用的线程数之间没有真正的联系。 I might initialize reusableObjects to have 10 objects, and say due to some limitations, ThreadPool can run only 3 threads for my MultiThreadedGenerate() method, then I'm wasting memory. 我可能将reusableObjects初始化为具有10个对象,并且说由于某些限制,ThreadPool只能为我的MultiThreadedGenerate()方法运行3个线程,然后浪费了内存。

So by getting rid of paramObjects , how can the above code be refined in a way that as soon as one thread completes its job, that thread returns its taskIndex (or the reusableObj ) it used and no longer needs so that it becomes available to the next value. 因此,通过摆脱paramObjects ,如何以一种线程完成其工作后,该线程返回其taskIndex使用且不再需要的taskIndex (或reusableObj )的方式改进上述代码,以便对下一个值。 Also, the code should create a reUsableObject and add it to some collection only when there is a demand for it. 另外,代码应该创建一个reUsableObject并且仅在有需求时才将其添加到某个集合中。 Is using a Queue here a good idea ? 在这里使用队列是个好主意吗?

Thank you. 谢谢。

There's really no reason to do your own manual threading and task management any more. 确实没有任何理由再进行自己的手动线程和任务管理。 You could restructure this to a more loosely-coupled model using Task Parallel Library (and possibly System.Collections.Concurrent for result collation). 您可以使用Task Parallel Library (可能还有System.Collections.Concurrent用于结果整理)将其重组为耦合程度更松散的模型。

Performance could be further improved if you don't need to wait for a full complement of work before handing off each Task for processing. 如果您无需等待全部工作完成再交出每个Task进行处理,则可以进一步提高性能。

TPL came along in .Net 4.0 but was back-ported to .Net 3.5 . TPL出现在.Net 4.0中,但被反向移植到.Net 3.5中 Download here . 在这里下载。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM