一次性调用太多Delegate.BeginInvoke会有问题吗?

3

我正在清理一些旧代码,将其转换为异步工作。

psDelegate.GetStops decStops = psLoadRetrieve.GetLoadStopsByLoadID;
var arStops = decStops.BeginInvoke(loadID, null, null);
WaitHandle.WaitAll(new WaitHandle[] { arStops.AsyncWaitHandle });
var stops = decStops.EndInvoke(arStops);

以下是我在异步工作方面所做的单个示例。我的计划是运行近20个不同的委托。它们都将调用BeginInvoke并等待直到所有委托完成后再调用EndInvoke
我的问题是,运行这么多委托会导致问题吗?我知道BeginInvoke使用线程池来执行任务,而线程池有25个线程的限制。虽然20个委托在此限制之下,但系统的其他部分也可能使用线程池中的任意数量线程。
谢谢!

线程池限制为每个处理器核心25个 ;) - TomTom
@TomTom 它已经增加到每个核心250个。http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx - Brian Rasmussen
2个回答

2
不,线程池管理器是为了应对这种情况而设计的。它不会让所有线程池线程同时运行。它开始时允许与 CPU 核心数相同数量的线程运行。只要一个线程完成,它就允许另一个线程运行。
每隔半秒钟,如果活动线程没有完成,它就会介入。它会假定它们被卡住了,并允许另一个线程运行。在 2 个核心的 CPU 上,您现在将有 3 个线程在运行。
在 2 个核心的 CPU 上达到最大值 500 个线程需要一段时间。您必须拥有超过 4 分钟不完成的线程。如果您的线程表现出这种特性,那么您不希望使用线程池线程。

更不用说500个托管线程将占用500 MB的堆栈空间了。 - Brian Rasmussen

1

当前默认的每个处理器的最大线程数是250,因此实际上除非您的应用程序只是不断调用BeginInvoke,否则不应该有限制。请参阅http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx。此外,线程池将尝试在创建新线程的开销较大时重用现有线程以减少开销。如果您的调用都很快,您可能看不到线程池创建很多线程。

对于长时间运行或阻塞任务,通常最好避免使用线程池并自己管理线程。

然而,在大多数当前的计算机上,尝试调度那么多线程可能不会产生最佳结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接