gpt4 book ai didi

c# - 在 C# 中从主线程以外的线程访问 COM 对象速度慢

转载 作者:太空狗 更新时间:2023-10-30 00:15:53 24 4
gpt4 key购买 nike

我有一个专有的 COM 库,它返回一个整数数组(当然是它们自己专有的格式)。当我从主 UI 线程访问这个数组时,一切都很好并且运行很快。当我从另一个线程访问它时,访问速度很慢。下面是一些示例代码。

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
}

为什么会这样?我有什么办法可以加快速度吗?如果我使用多处理而不是多线程,那么我是否有希望获得良好的性能? (虽然,听起来要复杂得多。)

更新:

我对下面的答案很满意,但想在这里添加一些数据以供引用(我自己的和其他人的)。

如上所示在新线程中创建和访问对象每次访问大约需要 12ns。据推测,该对象实际上是在主线程上创建的,速度慢是因为从那里编码数据。

如果您在主线程上显式创建数据,但在标记为单线程单元的新线程中访问它,则访问时间会更慢,每次访问需要 15 纳秒。我想 .NET 一定有一些额外的开销来保持公寓的美观,尽管我担心我不知道这些开销是多少。虽然只有 2-3 ns 的差异,但它不会太大。

如果您在标记为 STA 的新线程上创建和访问对象,则每次访问的时间会减少 0.2ns。但是这个新线程真的安全吗?这是我想的另一个问题的问题。

最佳答案

COM 对象具有线程亲和性,它们可以告诉 COM 它们不是线程安全的。使用注册表中的键“ThreadingModel”键。绝大多数人这样做,要么通过指定“公寓”,要么只是省略 key 。它在 .NET 中不太明确,它使用 MSDN 告诉您类不是线程安全的,并且不会以其他方式提醒您忘记阅读这篇文章。绝大多数 .NET 类都不是线程安全的,与 COM 组件类没有区别。与 .NET 不同,COM 确保以线程安全的方式调用它们。通过自动编码(marshal)对创建对象的线程的调用。

也就是说,没有并发,很慢。

取得成功的唯一方法是创建您自己的 Thread 并调用其 SetApartmentState() 方法以切换到 STA,这是非线程安全的 COM 对象的幸福家园。您还必须在该线程上创建 COM 对象。而且您可能必须泵送消息循环以使其保持事件状态,这是 STA 的要求。永远不要阻塞线程。这些是使它成为非线程安全类的幸福归宿的原因,如果所有调用都在一个线程上进行,那么就不会出错。您可以找到此类线程的示例实现 in this answer .

或者换句话说,当线程与非线程安全的对象一起使用时,天下没有免费的午餐。 .NET 让您在需要时忘记使用 lock 来开枪,而 COM 使它自动进行。以这种方式单腿跳动的程序员要少得多,但效率不高。

关于c# - 在 C# 中从主线程以外的线程访问 COM 对象速度慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10643652/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com