我在一个循环中调用了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());
}
}
答案 0 :(得分:6)
您不希望为此创建10个线程。最佳情况是拥有与核心一样多的活动线程。您会发现ThreadPool.MinThreads等于PC上的逻辑CPU数量。
将创建其他线程,但ThreadPool会故意延迟。 Fx4中的算法已得到改进,请参阅this page。快速查看底部的图片将有助于您了解原理。
额外的线程只有助于补偿被阻塞的线程,但这很难完全正确。
答案 1 :(得分:4)
线程池在启动新线程之前故意等待了一段时间 - 如果代表们无论如何快速执行(听起来像是这样),在几个线程上执行它们比启动新线程更有效。
当所有线程池线程都已存在时 分配给任务,线程池 没有立即开始创建 新的空闲线程。避免 不必要地分配堆栈空间 对于线程,它会创建新的空闲 线程间隔。间隔是 目前半秒钟,虽然它 可能会在以后的版本中改变 .NET Framework..NET Framework。