使用现有 API 的 .Net 中事件的线程上下文是什么

本文关键字:事件 线程 上下文 是什么 Net API | 更新日期: 2023-09-27 17:47:22

当使用API处理.Net中的异步事件时,我发现自己无法预测库将如何针对大量对象进行扩展。

例如,使用 Microsoft.Office.Interop.UccApi 库,当我创建终结点时,它会在发生电话事件时获取事件。现在,假设我想创建 1000 个终结点。每个终结点的事件数很少,但 API 中后台发生的事情是否能够跟上事件流?我不知道,因为它从来没有说它是如何构建的。

假设我想在主线程中创建所有 1000 个对象。然后我想将 Login 方法放入一个大型线程池中,以便所有对象并行登录。然后,一旦所有对象都记录在下一阶段,就会开始。

API 引发的事件回调是否发生在原始创建线程中?单独的线程池?还是我使用 ThreadPool.QueueUserWorkItem 访问的同一线程池?

我会更好地将每个对象放在它自己的线程中吗?在每个线程中对几个对象进行分组?或者只是在主线程中创建所有 1000 个对象并通过 .Net 魔术一切正常吗?

感谢

使用现有 API 的 .Net 中事件的线程上下文是什么

互操作程序集中的事件只是 COM 连接点的包装器。来自连接点的调用到达的线程取决于在该连接点上提供建议的对象的线程模型。COM 将为此确保正确的线程切换。

如果对象是在主线程(在 .Net 中通常是 STA)上实现的,则所有事件都应到达同一线程。如果您希望调用从 COM 线程池(我认为与 CLR 线程池相同)的随机线程上到达,则需要在配置为 MTA 的线程上创建对象。

我强烈建议不要为每个对象创建一个线程:1)如果您将这些线程创建为 STA,则每个线程都将有一个消息队列,从而占用系统资源;2)如果您将它们创建为MTA,则无法保证事件调用将到达您的线程;3)您将有1000个空闲线程无所事事,只是等待事件关闭;4)启动和关闭所有这些线程会对您的应用程序产生可怕的性能成本。

这实际上取决于很多事情,主要是您的硬件有多强大。线程池确实有一定数量的线程(您可以增加),它将可用于您的应用程序。因此,如果所有事件同时触发,则某些事件很可能会等待片刻,而线程池则等待线程再次空闲。权衡是,您也不会一直创建新线程的性能影响。创建 1000 个线程可能也不是正确的答案。

事实证明,这是理想的,这既是因为重用线程的性能提升,还因为同时运行 1000 个线程可能会使内存/CPU 使用率超过其价值。

我只是想指出,在 .NET 2.0 及更高版本中,可以使用 ThreadPool.SetMaxThreads() 以编程方式增加线程池中的最大线程数。鉴于此,您可以对线程数设置硬上限,从而确保调度程序不会因开销而瘫痪。

在这种情况下更有用,您可以使用 ThreadPool.SetMinThreads() 设置最小线程数。有了这个,您可以确保在应用程序启动时只支付Franci所说的"可怕的性能价格"。您可以平衡这一点与预期的用户数量峰值,从而确保您不会创建大量新线程。

单个新线程创建不会破坏您。我担心的是需要同时创建大量线程的情况。如果你能说这只会在启动时发生,那你就是金子。