Блокировка многопоточности с помощью объекта InternetExplorer - PullRequest
0 голосов
/ 10 июля 2020

Я пытаюсь получить документ из объекта InternetExplorer.

У меня возникла проблема с застреванием кода при вызове функции на очень длительные периоды времени - на несколько часов. Эта проблема возникает редко. Я отследил проблему до того, как мой код взаимодействует с InternetExplorer. В попытке исключить доступ к InternetExplorer.Document я поместил этот код в отдельный поток.

Однако теперь он терпит неудачу в 100% случаев. Я использовал код как можно больше в потоке, чтобы отслеживать точную проблему, и это object objDoc = win.Document; ниже. Отладчик доходит до этой строки, но не проходит мимо нее. Без потоковой передачи на возврат документа обычно уходили миллисекунды, но иногда и секунды. С потоковой передачей теперь требуется более 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;
    }
}

1 Ответ

0 голосов
/ 10 июля 2020

Я наконец-то смог решить проблему. Кто-то, кто разбирается в потоках лучше меня, может объяснить, почему. Я бы предположил, однако, что переключение потоков при попытке доступа к COM привело к его зависанию - вынуждая основной поток ждать, пока дочерний поток завершит работу. sh устраняет проблему.

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, тогда приложение не отвечало бы на ввод пользователя в течение пяти минут. Однако мое приложение представляет собой консольное приложение, которое незаметно работает на виртуальной машине для обработки и распределения входящей работы. Короткая пауза не вредит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...