多线程锁定 InternetExplorer 对象

Multithreading locking up with InternetExplorer object

我正在尝试从 InternetExplorer 对象获取文档。

我一直遇到一个问题,我的代码在很长一段时间内卡在函数调用中 - 持续了几个小时。这个问题很少发生。我已将问题追溯到我的代码如何与 InternetExplorer 交互。为了排除访问 InternetExplorer.Document 的可能性,我将该代码放入了一个单独的线程中。

但是,它现在有 100% 的时间失败。我已在线程中尽可能多地分解代码以跟踪确切的问题,它在下面的 object objDoc = win.Document; 中。调试器到达该行但从未超过它。在没有线程的情况下,return 文档通常需要几毫秒,尽管偶尔需要几秒钟。使用线程现在需要超过 5 分钟,这是当我让代码在主线程中抛出异常时。

有人知道我编写的线程代码的问题所在吗?

private InternetExplorer window;
private object lockObject = new object();
private HTMLDocument childThreadDocument;
private Thread childThread;

public HTMLDocument GetDocument()
{
    DateTime start = DateTime.Now;
    childThread = new Thread(() => threadedGetDocument());
    childThread.Start();
    while (true)
    {
        if ((DateTime.Now - start).TotalMinutes > 5) throw new Exception();
        lock (lockObject)
        {
            if (childThreadDocument != null) return childThreadDocument;
        }
    }
}

private void threadedGetDocument()
{
    InternetExplorer win = window;
    object objDoc = win.Document;
    HTMLDocument doc = (HTMLDocument)objDoc;
    lock (lockObject)
    {
        childThreadDocument = doc;
    }
}

我终于能够解决这个问题。比我更了解线程的人可能能够解释原因。我猜想在尝试访问 COM 时切换线程会导致它挂起 - 强制主线程等待子线程完成解决了这个问题。

public HTMLDocument GetDocument()
{
    DateTime start = DateTime.Now;
    childThread = new Thread(() => threadedGetDocument());
    childThread.Start();
    childThread.Join(new TimeSpan(0, 5, 0));
    lock (lockObject)
    {
        if (childThreadDocument != null)
            return childThreadDocument;
        else 
            throw new ExecutionEngineException("Failed to open IE Document");
    }
}

请注意,如果您正在创建一个需要响应的应用程序,那么实施这将是一个糟糕的想法。如果在 GUI 线程中进行这样的调用,则应用程序将在长达五分钟的时间内不会响应用户输入。但是,我的应用程序是一个控制台应用程序,可以在 VM 上安静地运行以处理和分发传入的工作。短暂的停顿不会造成任何伤害。