简体   繁体   English

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

[英]What's the thread context for events in .Net using existing APIs?

When using APIs handling asynchronous events in .Net I find myself unable to predict how the library will scale for large numbers of objects. 当使用API​​处理.Net中的异步事件时,我发现自己无法预测该库如何扩展大量对象。

For example, using the Microsoft.Office.Interop.UccApi library, when I create an endpoint it gets events when phone events happen. 例如,使用Microsoft.Office.Interop.UccApi库,当我创建端点时,它会在电话事件发生时获取事件。 Now let's say I want to create 1000 endpoints. 现在,假设我要创建1000个端点。 The number of events per endpoint is small, but is what's happening behind the scenes in the API able to keep up with the event flow? 每个端点的事件数量很小,但是API幕后发生的事情能够跟上事件流的发展吗? I don't know because it never says how it's architected. 我不知道,因为它从不说它是如何设计的。

Let's say I want to create all 1000 objects in the main thread. 假设我要在主线程中创建所有1000个对象。 Then I want to put the Login method into a large thread pool so all objects login in parallel. 然后,我想将Login方法放入一个大线程池中,以便所有对象并行登录。 Then once all the objects have logged in the next phase will begin. 然后,一旦所有对象都登录,下一阶段将开始。

Are the event callbacks the API raises happening in the original creating thread? API引发的事件回调是否在原始创建线程中发生? A separate threadpool? 一个单独的线程池? Or the same threadpool I'm accessing with ThreadPool.QueueUserWorkItem? 还是我正在使用ThreadPool.QueueUserWorkItem访问的同一个线程池?

Would I be better putting each object in it's own thread? 我将每个对象放在自己的线程中会更好吗? Grouping a few objects in each thread? 在每个线程中分组几个对象? Or is it fine just creating all 1000 objects in the main thread and through .Net magic it will all be OK? 还是只在主线程中创建所有1000个对象,然后通过.Net magic一切正常就可以了吗?

thanx 感谢名单

The events from interop assemblies are just wrappers around the COM connection points. 来自互操作程序集的事件只是COM连接点周围的包装器。 The thread on which the call from the connection point arrive depends on the threading model of the object that advised on that connection point. 来自连接点的调用到达的线程取决于在该连接点上建议的对象的线程模型。 COM will ensure the proper thread switching for this. COM将为此确保适当的线程切换。

If your objects are implemented on the main thread, which in .Net is usually an STA, all events should arrive on that same thread. 如果对象是在主线程(在.Net中通常是STA)上实现的,则所有事件都应到达同一线程上。 If you want your calls to arrive on a random thread from the COM thread pool (which I think is the same as the CLR thread pool), you need to create your objects on a thread that is configured as an MTA. 如果希望调用从COM线程池(我认为与CLR线程池相同)到达随机线程,则需要在配置为MTA的线程上创建对象。

I would strongly advise against creating a thread for each object: 1) If you create these threads as STA, each of them will have a message queue, waisting system resource; 我强烈建议不要为每个对象创建线程:1)如果将这些线程创建为STA,则每个线程都会有一个消息队列,占用系统资源; 2) If you create them as MTA, nothing guarantees you the event call will arrive on your thread; 2)如果将它们创建为MTA,则不能保证事件调用将到达您的线程; 3) You'll have 1000 idle threads doing nothing and just waiting on an event to shutdown; 3)您将有1000个空闲线程不执行任何操作,仅等待事件关闭; and 4) Starting up and shutting down all these threads will have terrible perf cost on your application. 和4)启动和关闭所有这些线程将对您的应用程序造成可怕的性能损失。

It really depends on a lot of things, primarily how powerful your hardware is. 它实际上取决于很多事情,主要取决于硬件的功能。 The threadpool does have a certain number of threads (which you can increase) that it will make available for your application. 线程池确实具有一定数量的线程(可以增加),这些线程将可用于您的应用程序。 So if all of your events are firing at the same time some will most likely be waiting for a few moments while your threadpool waits for threads to become free again. 因此,如果所有事件都在同一时间触发,则在线程池等待线程再次变为空闲时,某些事件很可能在等待片刻。 The tradeoff is that you don't have the performance hit of creating new threads all the time either. 折衷方案是您也不总是一直在创建新线程时性能下降。 Probably creating 1000 threads isn't the right answer either. 可能创建1000个线程也不是正确的答案。

It may turn out that this is ideal, both because of the performance gains in reusing threads but also because having 1000 threads all running simultaneously might be more memory / CPU usage than it's worth. 事实证明,这是理想的选择,这不仅是因为重用线程可以提高性能,而且还因为同时运行1000个线程可能会占用更多的内存/ CPU资源。

I just wanted to note that in .NET 2.0 and greater it's possible to programmatically increase the maximum number of threads in the thread pool using ThreadPool.SetMaxThreads() . 我只想指出,在.NET 2.0及更高版本中,可以使用ThreadPool.SetMaxThreads()以编程方式增加线程池中的最大线程数。 Given this you can put a hard cap on the number of threads and so ensure the scheduler won't be brought to it's knees by the overhead. 鉴于此,您可以对线程数进行硬性限制,从而确保调度程序不会因开销而屈服。

Even more useful in this sort of case, you can set the minimum number of threads with ThreadPool.SetMinThreads() . 在这种情况下甚至更有用,您可以使用ThreadPool.SetMinThreads()设置最小线程数。 With this you can ensure that you only pay the "horrible performance price" Franci is talking about once, at application startup. 这样,您可以确保在应用程序启动时,Franci只是在说一次“可怕的性能价格”。 You could balance this against the expected number peak of users and so ensure you won't be creating tons of new threads. 您可以将其与预期的用户高峰之间取得平衡,从而确保您不会创建大量新线程。

A single new thread creation won't destroy you. 一个新的线程创建不会破坏您。 What I would be worried about is the case where a lot of threads need to be created at the same time. 我担心的是需要同时创建许多线程的情况。 If you can say that this will only happen at startup you would be golden. 如果您可以说这只会在启动时发生,那将是无与伦比的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM