use*_*861 4 c# com multithreading
我有一个专有的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
}
Run Code Online (Sandbox Code Playgroud)
为什么会这样?我有什么方法可以加快速度吗?如果我使用多处理而不是多线程,那么我是否有希望获得良好的性能?(虽然,听起来更复杂.)
更新:
我对以下答案感到满意,但想在这里添加一些数据以供参考(我自己和其他人的).
如上所示在新线程中创建和访问对象,每次访问大约12ns.据推测,该对象实际上是在主线程上创建的,慢速是由于从那里封送数据.
如果您在主线程上显式创建数据但在标记为单线程单元的新线程中访问它,则访问时间会更慢,每次访问时间为15 ns.我想.NET必须有一些额外的开销来保持公寓的美观,尽管它让我担心我不知道那是什么开销.只有2-3 ns的差异,但不一定要多.
如果您在标记为STA的新线程上创建并访问该对象,则每次访问时间会以.2ns的速度消失.但这个新线程真的安全吗?这是我想到的另一个问题的问题.
COM对象具有线程关联性,它们可以告诉COM它们不是线程安全的.使用注册表中的密钥,"ThreadingModel"键.绝大多数都是通过指定"公寓"或只是省略键.它在.NET中不太明确,它使用MSDN告诉您类不是线程安全的,并且不会提醒您忘记阅读文章.绝大多数.NET类都不是线程安全的,与COM coclass没有区别.与.NET不同,COM确保以线程安全的方式调用它们.通过自动封送对创建对象的线程的调用.
换句话说,没有并发性和非常慢.
获得成功的唯一方法是创建自己的Thread并调用其SetApartmentState()方法切换到STA,这是一个非线程安全的COM对象的幸福家园.而且你还必须在该线程上创建COM对象.并且您可能必须抽取消息循环以使其保持活动,这是STA的要求.永远不会阻止线程.如果所有调用都在一个线程上进行,则不会出现任何问题,这些事情使得它成为一个非线程安全的类的幸福之家.您可以在此答案中找到此类线程的示例实现.
或者换句话说,当使用非线程安全对象的线程时,没有免费的午餐..NET允许你在必要时忘记使用锁定来射击你的脚,COM使它自动化.很少有程序员以这种方式跳上一条腿,但效率不高.