运行一段没有阻塞的代码,使用在主线程中创建的COM对象

时间:2012-02-08 19:13:14

标签: c# wpf multithreading com

我有一个慢的方法,我想在一个单独的线程中运行。 此方法使用对应用程序主线程中创建的COM对象的调用。

让我们假设代码很慢:

var bwImg = image.GetBitonalImage(); // <- slow image is a COM created in main thread
viewer.Document = bwImg; // <-- ATL control accepting the B/W COM image 

如果这很重要,我在WPF应用程序中执行此操作,并且'viewer'位于WinFormsHost中。

我认为这样做会使这个异步并且不会阻止应用程序的运行:

var t = new Thread((ThreadStart)(() =>
{
    var bwImg = image.GetBitonalImage(); // <- this is in separate thread
    Dispatcher.Invoke((Action)(() =>
    {
        viewer.Document = bwImg; // <- this again on the main
    }));
}));
t.Start();

我可以在稍后的时间显示图像,我不在乎多久。

但是,应用程序以相同的方式被阻止。 我做了分析,确实大部分时间花在了GetBitonalImage上,而且几乎没有用于'viewer.Document = bwImg'。

完全删除代码会使应用程序响应,因此不会出现其他代码错误。

在此之后还有其他代码使用相同的图像COM对象(不是B / W结果而是原始文件)。

这是正确的方法吗?问题可能是因为COM对象方法调用了吗?

2 个答案:

答案 0 :(得分:4)

您的COM对象线程是否安全?如果不是,那么它可能在STA(单线程单元)模式下初始化,这将使用STA线程来完成其工作。因此,即使您启动了一个新线程,它也会切换回STA线程,阻止您的UI事件。如果您可以控制COM库的源代码,则可以更改这些设置,只要代码实际上是线程安全的。

编辑:在相关帖子部分找到此链接,它可能适用于您。 UI thread is blocking a background thread calling a COM object

答案 1 :(得分:0)

在这种情况下纠正有很多不同的含义。 :/

  

问题可能是因为COM对象方法调用吗?

好吧,如果您删除该调用并且应用程序运行得更快,那么我会说:是..

  

这是正确的方法吗?

最好的答案是一个问题:它有效吗?如果是这样,那么你可能走在正确的轨道上。

很难说是肯定的,因为我不知道com对象的作用。它是专为单线程操作而设计的吗?如果多个线程创建实例,它将如何表现?换句话说,com对象本身是线程安全吗?我想你很快就会找到答案。

现在提出一个更广泛的问题:

  

这是处理长时间运行的异步进程的正确方法吗?

是。