线程池执行延迟怀疑

时间:2010-08-14 07:31:51

标签: c++-cli

我在一个循环中调用了10个委托的BeginInvoke。线程池不使用10个线程,而只使用两个/三个线程来执行委托。有人可以解释一下这个原因吗?委托执行只需几毫秒(小于10毫秒)。

当我在调用BeginInvoke之前记录了threadpool参数时,它表明Min Threads = 2,Max Threads = 500,Available threads = 498。


当我调用以下托管c ++代码时,我遇到了问题。

void EventHelper::FireAndForget(Delegate^ d, ... array<Object^>^ args)
            {
                try
                {
                    if (d != nullptr)
                    {                                           
                        array<Delegate^>^ delegates = d->GetInvocationList();   

                        String^ message1 = String::Format("No of items in the event {0}",delegates.Length);
                        Log(LogMessageType::Information,"EventHelper.FireAndForget", message1);

                        // Iterating through the list of delegate methods.
                        for each(Delegate^ delegateMethod in delegates)
                        {
                            try
                            {
                                int minworkerThreads,maxworkerThreads,availworkerThreads, completionPortThreads;
                                ThreadPool::GetMinThreads(minworkerThreads, completionPortThreads);
                                ThreadPool::GetMaxThreads(maxworkerThreads, completionPortThreads);
                                ThreadPool::GetAvailableThreads(availworkerThreads, completionPortThreads);

                                String^ message = String::Format("FireAndForget Method {0}#{1} MinThreads - {2}, MaxThreads - {3} AvailableThreads - {4}",
                                                delegateMethod->Method->DeclaringType, delegateMethod->Method->Name, minworkerThreads, maxworkerThreads, availworkerThreads);

                                Log(LogMessageType::Information,"EventHelper.FireAndForget", message);

                                DynamicInvokeAsyncProc^ evtDelegate = gcnew DynamicInvokeAsyncProc(this, &EventHelper::OnTriggerEvent);
                                evtDelegate->BeginInvoke(delegateMethod, args, _dynamicAsyncResult, nullptr); //FIX_DEC_09 Handle Leak    
                            }
                            catch (Exception^ ex)
                            {
                                String^ message = String::Format("{0} : DynamicInvokeAsync of '{1}.{2}' failed", _id,
                                                                    delegateMethod->Method->DeclaringType, d->Method->Name);

                                Log(LogMessageType::Information,"EventHelper.FireAndForget", message);                              
                            }
                        }
                    }
                    else
                    {                   
                    }
                }
                catch (Exception^ e)
                {
                    Log(LogMessageType::Error, "EventHelper.FireAndForget", e->ToString());
                }

            }

这是代理

中给出的方法
void EventHelper::OnTriggerEvent(Delegate^ delegateMethod, array<Object^>^ args)
            {
                try
                {
                    int minworkerThreads,maxworkerThreads,availworkerThreads, completionPortThreads;
                    ThreadPool::GetMinThreads(minworkerThreads, completionPortThreads);
                    ThreadPool::GetMaxThreads(maxworkerThreads, completionPortThreads);
                    ThreadPool::GetAvailableThreads(availworkerThreads, completionPortThreads);

                    String^ message = String::Format("OnTriggerEvent Method {0}#{1} MinThreads - {2}, MaxThreads - {3} AvailableThreads - {4}",
                                    delegateMethod->Method->DeclaringType, delegateMethod->Method->Name, minworkerThreads, maxworkerThreads, availworkerThreads);
                    Log(LogMessageType::Information,"EventHelper::OnTriggerEvent", message);

                    message = String::Format("Before Invoke Method {0}#{1}",
                                                delegateMethod->Method->DeclaringType, delegateMethod->Method->Name);
                    Log(LogMessageType::Information,"EventHelper::OnTriggerEvent", message);

                    // Dynamically invokes (late-bound) the method represented by the current delegate. 
                    delegateMethod->DynamicInvoke(args);
                    message = String::Format("After Invoke Method {0}#{1}",
                                                delegateMethod->Method->DeclaringType, delegateMethod->Method->Name);
                    Log(LogMessageType::Information,"EventHelper::OnTriggerEvent", message);
                }
                catch (Exception^ ex)
                {
                    Log(LogMessageType::Error, "EventHelper.OnTriggerEvent", ex->ToString());
                }
            }

2 个答案:

答案 0 :(得分:6)

您不希望为此创建10个线程。最佳情况是拥有与核心一样多的活动线程。您会发现ThreadPool.MinThreads等于PC上的逻辑CPU数量。

将创建其他线程,但ThreadPool会故意延迟。 Fx4中的算法已得到改进,请参阅this page。快速查看底部的图片将有助于您了解原理。

额外的线程只有助于补偿被阻塞的线程,但这很难完全正确。

答案 1 :(得分:4)

线程池在启动新线程之前故意等待了一段时间 - 如果代表们无论如何快速执行(听起来像是这样),在几个线程上执行它们比启动新线程更有效。

来自docs for ThreadPool

  

当所有线程池线程都已存在时   分配给任务,线程池   没有立即开始创建   新的空闲线程。避免   不必要地分配堆栈空间   对于线程,它会创建新的空闲   线程间隔。间隔是   目前半秒钟,虽然它   可能会在以后的版本中改变   .NET Framework..NET Framework。