Рекурсивные HTTP-вызовы демонстрируют различное поведение в среде IDE по сравнению с развернутым исполняемым файлом

Код выполняет HTTP-вызовы к открытому представлению дерева SVN. Затем он анализирует HTML и добавляет файлы для справки позже, чтобы извлечь их и отправить пользователю. Это делается в приложении WPF. Ниже приведен код вместе с изображением, показывающим структуру каталогов.

    private readonly String _baseScriptURL = @"https://xxxxxxxxxx/svn/repos/xxxxxxxxxx/trunk/scripts/vbs/web/";

    private void FindScripts(String url, ref ICollection files)
    {
        //MyFauxMethod();
        StringBuilder output = new StringBuilder();

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
        request.Credentials = new Credentials().GetCredentialCache(url);

        _logger.Log("Initiating request [" + url + "]", EventType.Debug);

        try
        {
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            using (Stream stream = response.GetResponseStream())
            {
                _logger.Log("Response received for request [" + url + "]", EventType.Debug);

                int count = 0;
                byte[] buffer = new byte[256];
                while ((count = stream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    if (count < 256)
                    {
                        List trimmedBuffer = buffer.ToList();
                        trimmedBuffer.RemoveRange(count, 256 - count);

                        String data = Encoding.ASCII.GetString(trimmedBuffer.ToArray());
                        output.Append(data);
                    }
                    else
                    {
                        String data = Encoding.ASCII.GetString(buffer);
                        output.Append(data);
                    }
                }
            }

            String html = output.ToString();

            HTMLDocument doc = new HTMLDocumentClass();
            IHTMLDocument2 doc2 = (IHTMLDocument2)doc;
            doc2.write(new object[] { html });

            IHTMLElementCollection ul = doc.getElementsByTagName("li");
            doc2.close();
            doc.close();                

            foreach (IHTMLElement item in ul)
            {
                if (item != null &&
                    item.innerText != null)
                {
                    String element = item.innerText.Trim().Replace(" ", "%20");

                    //nothing to do with going up a dir
                    if (element == "..")
                        continue;

                    _logger.Log("Interrogating [" + element + "]", EventType.Debug);

                    String filename = System.IO.Path.GetFileName(element);
                    if (String.IsNullOrEmpty(filename))
                    {
                        //must be a directory; recursively search if honored dir
                        if (!_ignoredDirectories.Contains(element))
                        {
                            _logger.Log("Searching directory [" + element + "]", EventType.Debug);
                            FindScripts(url + System.IO.Path.GetDirectoryName(element) + "/", ref files);
                        }
                        else
                            _logger.Log("Ignoring directory [" + element + "]", EventType.Debug);
                    }
                    else
                    {
                        //add honored files to list for parsing meta data later
                        if (_honoredExtensions.Contains(System.IO.Path.GetExtension(filename)))
                        {
                            files.Add(url + filename);
                            _logger.Log("Added file [" + (url + filename) + "]", EventType.Debug);
                        }
                    }
                    //MyFauxMethod();
                }
                //MyFauxMethod();
            }

        }
        catch (Exception e)
        {
            _logger.Log(e);
        }
        //MyFauxMethod();
    }


    private void MyFauxMethod()
    {
        int one = 1;
        int two = 2;
        int three = one + two;
    }

Directory structure

Прежде всего, приносим свои извинения за длинный блок кода; однако я хотел убедиться, что весь метод был понят. Существующая проблема применима только при использовании сгенерированного исполняемого файла Release вне среды IDE. Если сборка Release выполняется в среде IDE, она работает без каких-либо проблем.

Кроме того, проблема не возникает при выполнении сгенерированной сборки Debug вне среды IDE или внутри среды IDE; он работает надлежащим образом в обоих сценариях.

Проблема в том, что рекурсивные вызовы останавливают продолжение кода после метода рекурсии. В потоке не возникает никаких исключений; все просто останавливается перед перемещением в каждый каталог, как это происходит в других сборках.

Строки журнала сборки Release выглядят так ...

Инициирующий запрос [ https: // xxxxxxxxx / svn / repos / xxxxxxxxx / trunk / scripts / vbs / web /]
Получен ответ на запрос [ https: // xxxxxxxxx / svn / repos / xxxxxxxxx / trunk / scripts / vbs / web /]
Опрос [beq /]
Поиск каталог [beq /]
Запуск запрос [ https: // xxxxxxxxx / svn / repos / xxxxxxxxx / trunk / scripts / vbs / web / beq /]
Получен ответ на запрос [ https: // xxxxxxxxx / svn / repos / xxxxxxxxx / trunk / scripts / vbs / web / beq /]
Опрос [core /]
Поиск каталог [core /]
Запуск запрос [ https: // xxxxxxxxx / svn / repos / xxxxxxxxx / trunk / scripts / vbs / web / beq / core /]
Получен ответ на запрос [ https: // xxxxxxxxx / svn / repos / xxxxxxxxx / trunk / scripts / vbs / web / beq / core /]
Опрос [BEQ-Core% 20Library.vbs]
Добавлен файл [ https: //xxxxxxxxx/svn/repos/xxxxxxxxx/trunk/scripts/vbs/web/beq/core/BEQ-Core%20Library.vbs]
Допрос [одноразовые /]
Поиск в каталоге [одноразовые /]
Исходный запрос [ https: // xxxxxxxxx / svn / repos / xxxxxxxxx / trunk / scripts / vbs / web / beq / one-offs /]
Получен ответ на запрос [ https: // xxxxxxxxx / svn / repos / xxxxxxxxx / trunk / scripts / vbs / web / beq / one-offs /]
Рекурсивный поиск скриптов занял [6] с. [140] мс для [1]
Анализ метаданных потребовалось [0] м [0] с [906] мс для [1]
Общее время заняло [0] м [7] с [46] мс

ОБНОВЛЕНИЕ:

После добавления примерно 3 дополнительных строк журнала во время отладки, теперь он работает должным образом. Возникающий вопрос: почему? Попытка изолировать проблемный код в отдельном приложении не дает отрицательных результатов.

Есть идеи, почему это могло произойти?

ОБНОВЛЕНИЕ:

Изменение строк журнала для вызова искусственного метода дало те же результаты. Я добавил вызовы метода faux и метода faux в приведенном выше источнике, 1 у входа в метод и 3 внизу. Сами звонки закомментированы, чтобы их было легче найти; они НЕ прокомментированы в реальном коде.

Если я закомментирую любой из 4 добавленных ложных вызовов метода, он перестанет работать. Опять же, это только в выпуске через CTRL + F5 или за пределами IDE полностью.

ОБНОВЛЕНИЕ:

Добавлен .close () в экземпляры HtmlDocument для каждого fubaar ; такое же поведение по-прежнему проявляется.

ОБНОВЛЕНИЕ:

Добавлены явные вызовы GC для каждого fubaar; такое же поведение все еще наблюдается.

8
задан Aaron McIver 6 July 2011 в 22:36
поделиться