2010-08-14 110 views
3

我在一个循环中调用了10个代表的BeginInvoke。而不是使用10个线程,线程池只使用两个/三个线程来执行代理。有人可以解释一下这个原因吗?委托执行只需要几ms(少于10ms)。线程池执行延迟疑问

当我调用BeginInvoke的登录之前线程池参数它表明闵线程= 2,最大线程= 500,可用线程= 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()); 
       } 
      } 

回答

6

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

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

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

4

线程池刻意等待一小会儿之前启动新主题 - 如果代表们快速执行无论如何(这听起来像他们一样),在几个线程上执行它们比启动新线程更有效。

docs for ThreadPool

当所有线程池中的线程已经 分配给任务,线程池 不会立即开始创建新 空闲线程。为避免 不必要地为线程分配堆栈空间 ,它会间隔创建新的空闲线程 。间隔是 目前半秒,但它可能会在将来的版本的 .NET Framework..NET框架中更改 。