多线程锁定 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 上安静地运行以处理和分发传入的工作。短暂的停顿不会造成任何伤害。
我正在尝试从 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 上安静地运行以处理和分发传入的工作。短暂的停顿不会造成任何伤害。