访问COM对象线程以外主线程慢在C#

访问COM对象线程以外主线程慢在C#

本文介绍了访问COM对象线程以外主线程慢在C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个返回一个整数数组(当然在自己的专有格式)的专有COM库。当我从主UI线程访问此阵,一切都很好,迅速跑开。当我从另一个线程访问它时,访问速度很慢。有下面的一些示例代码。

I have a proprietary COM library that returns an array of integers (in their own proprietary format of course). When I access this array from the main UI thread, all is well and runs quickly. When I access it from another thread, the access is very slow. There's some sample code below.

private void test() {
    ProprietaryLib.Integers ints = ProprietaryLib.GetInts();
    int x;
    for(int i = 0; i < 500; i++)
        for(int j = 0; j < ints.Count; j++)
            x = ints[j];
}

private void button1_Click(object sender, EventArgs e) {
    test();  // Very little time
    new System.Threading.Thread(() => test()).Start(); // Lots of time
}



这是怎么回事?有没有什么办法,我加快这?如果我使用多线程处理,而不是多线程,你会不会再有获得良好表现的希望? (唉虽然听起来很复杂。)

Why is this happening? Is there any way for me to speed this up? If I use multi-processing instead of multi-threading, would I then have some hope of getting good performance? (Ugh though, sounds a lot more complicated.)

更新:

我很满意下面的答案,但是想在这里补充一些数据供参考(我自己和其他人的)。

I'm satisfied with the answers below, but wanted to add some data here for reference (my own and anyone else's).

创建并在一个新的线程访问对象如上图所示提供有关每个访问为12ns。据推测,该对象实际上是在主线程创建和速度慢的原因是从那里编组的数据。

Creating and accessing object in a new thread as shown above gives about 12ns per access. Presumably the object is actually created on the main thread and the slow speed is due to marshaling the data from there.

如果您明确的主线,但进入上创建数据它标记为单线程公寓一个新的线程,访问时间更慢,每访问15纳秒。我猜.NET必须有一些额外的开销,以保持公寓尼斯,虽然它让我担心,我不知道,开销是什么。只需2-3 ns的差异不会有太大虽然。

If you explicitly create the data on the main thread but access it in a new thread marked as a single threaded apartment, access time is even slower, at 15 ns per access. I guess .NET must have some extra overhead to keep the apartment nice, though it worries me that I don't know what that overhead is. With just a 2-3 ns difference it wouldn't have to be much though.

如果你创建和访问一个新的线程对象标记STA时间融化在每次访问.2ns。但是,这是新的线程真的安全吗?这是另一个问题,我想到一个问题。

If you create and access the object on a new thread marked STA the time melts away at .2ns per access. But is this new thread really safe? That's a question for another question I think.

推荐答案

COM对象已线程的亲和力,他们可以告诉COM,他们没有线程安全。在注册表中的一个键,的ThreadingModel键。绝大多数做的,通过指定公寓或只是省略键。它是在.NET不明确,它使用MSDN告诉你,类不是线程安全的,否则不提醒你,你忘了阅读文章。绝大多数.NET类都不是线程安全的,从COM组件类没有什么不同。与.NET,COM确保它们被调用的线程安全的方式。通过自动编组调用创建该对象的线程。

COM objects have threading affinity, they can tell COM that they are not thread-safe. With a key in the registry, the "ThreadingModel" key. The vast majority do, either by specifying "Apartment" or just omitting key. It is less explicit in .NET, it uses MSDN to tell you that classes are not thread-safe and doesn't otherwise remind you that you forgot to read the article. The vast majority of .NET classes are not thread-safe, no different from COM coclasses. Unlike .NET, COM makes sure that they get called in a thread-safe way. By automatically marshaling the call to the thread that created the object.

在换句话说,没有并发性和速度很慢。

In other words, no concurrency and very slow.

要出人头地的唯一方法是创建自己的线程,并调用其SetApartmentState()方法切换到STA,一个幸福家庭的COM对象不是线程安全的。你必须创建线程COM对象也是如此。你可能有泵消息循环,以保持它活着,一个STA要求。永远不要阻塞线程。这些都是使一个幸福的家是不是线程安全的,如果所有的调用上的有一个的线程做那么没有任何东西可以去错一类的事。你可以找到这个答案这样的线程的一个样本实现。

The only way to get ahead is to create your own Thread and call its SetApartmentState() method to switch to STA, a happy home for a COM object that isn't thread-safe. And you have to create the COM object on that thread as well. And you may have to pump a message loop to keep it alive, an STA requirement. And never block the thread. These are the things that make it a happy home for a class that is not thread-safe, if all the calls are made on one thread then nothing can go wrong. You can find a sample implementation of such a thread in this answer.

或者换句话说,使用与不是线程安全的对象线程时,有没有免费的午餐。 .NET允许您通过忘了使用的锁定的在需要的地方,COM使得自动拍摄你的脚。少了很多程序员跳跃单腿这种方式,但效率不高。

Or in other words, there is no free lunch when using threads with objects that are not thread-safe. .NET lets you shoot your foot by forgetting to use lock where needed, COM makes it automatic. A lot less programmers hopping on one leg that way, but not as efficient.

这篇关于访问COM对象线程以外主线程慢在C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!