Как отлаживать .NET удаленные вызовы? - PullRequest
6 голосов
/ 06 ноября 2008

У меня есть приложение со следующей базовой архитектурой:

Служба Windows (служба), которая регистрирует тип .NET (RemoteObject) для удаленного доступа (.NET Remoting). RemoteObject создает потоки не ThreadPool, которые используют ThreadPool для обработки ввода-вывода. Размер ThreadPool должен быть ограничен по определенной причине. Приложение с графическим интерфейсом использует .NET Remoting для доступа к RemoteObject.

Я заметил, что если размер ThreadPool слишком мал, приложение GUI будет зависать при вызове RemoteObject.

Мой вопрос: как я могу понять, почему это зависает, и почему поток RemoteObject будет затронут ThreadPool?

Это сводит меня с ума; спасибо за вашу помощь!

Ответы [ 4 ]

4 голосов
/ 21 сентября 2009

Оказывается, что инфраструктура удаленного взаимодействия .NET использует .NET ThreadPool (или совместно использует базовый ресурс), поэтому удаленные вызовы могут зависать, если все потоки ThreadPool используются вашим приложением.

4 голосов
/ 06 ноября 2008

Я не уверен, поможет ли это (я не могу сказать, является ли это вашей проблемой или нет), но если вы хотите отладить службу как запущенную, вы можете добавить это в свой код:

#if DEBUG
            if (!System.Diagnostics.Debugger.IsAttached)
                Debugger.Launch();
#endif

, и вы получите диалоговое окно с просьбой выбрать отладчик. Это простой способ присоединения к работающему экземпляру службы. Если ничего другого, это позволит вам взломать службу, когда пользовательский интерфейс зависает (нажав кнопку паузы на панели инструментов отладки), и проверить свои потоки и стек вызовов.

2 голосов
/ 06 ноября 2008

Это может быть не очень полезно, но я все равно его брошу.

При отладке сервисов и клиентов, которые общаются через удаленное взаимодействие, я обычно всегда запускаю два экземпляра отладчика: один для клиента и один для службы. Просто чтобы прояснить, у меня две копии Visual Studio. Для услуги вы можете использовать команду присоединения или вы можете изменить основной и начать вызов напрямую (в обход всего кода услуги).

Вот как я обычно включаю отладку, изменяя основной, и вам придется вызывать сервис DebugService, это действительно просто точка входа, которая вызывает start. Получив это, я просто включаю отладку службы, задав SERVICE_DEBUG или изменив #if, добавив '!'. Теперь вы в основном превратили свой сервис в консольное приложение.

#if SERVICE_DEBUG
            ServiceHost s = new ServiceHost();
            s.DebugService();
            Thread.Sleep( 300000000 );

#else
            ServiceBase.Run( ServicesToRun );
#endif

После того, как вы настроили и запустили, вы можете пройти через клиента, когда удаленные вызовы коснутся службы, вы можете пройти через код службы, что позволит вам отлаживать оба одновременно.

Из любопытства Вы вызываете удаленный объект непосредственно из потока GUI? Если это так, поток GUI будет блокироваться до завершения удаленного вызова. Это заблокирует весь графический интерфейс и сделает его не отвечающим. Это не решение проблемы, но если это так, и поток службы не возвращается, это также приведет к зависанию графического интерфейса.

1 голос
/ 07 ноября 2008

Несколько лет назад я разработал и внедрил критическую бизнес-систему, в которой использовалось .NET Remoting. У нас был клиент, реализованный в виде графического интерфейса Windows Forms, сервер, реализованный в виде службы Windows, и база данных SQL Server.

Я предназначен для устранения неполадок / отладки / разработки, поэтому одним из моих первых критериев проектирования было то, что я мог тривиально удалить всю реализацию .NET Remoting и запустить всю систему на своем рабочем столе. Таким образом, я мог деактивировать удаленное взаимодействие, изменив настройку одиночной логической конфигурации на «false» = off. Затем я мог бы устранять неполадки, отлаживать, разрабатывать полностью без издержек или вмешательства .NET Remoting.

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

Итак, для его реализации каждый клиент и серверный код использовали параметр конфигурации, чтобы решить, какой класс реализации создать для связи с другой стороной. Все взаимодействие происходило через пользовательский интерфейс C #, который имел два конкретных класса реализации на каждой стороне: один класс реализовывал связь с использованием .NET Remoting, другой класс реализовывал связь как прямое сквозное прохождение (прямые вызовы).

Только одна пара классов (по одному на каждой стороне) знала что-либо о .NET Remoting, поэтому изоляция была полной. Большую часть времени все разработчики работали с отключенным удаленным доступом, что было быстрее и проще. Когда им было нужно, в редких случаях они включали его (в основном только я или когда кто-то подключался к тестированию / производству для устранения неполадок).

Кстати, я сделал интерфейс удаленного взаимодействия очень простым: Публичный ответ выполнить (Запрос)

Кроме того, я также использовал упомянутую выше подсказку по запуску отладчика, и я согласен, что вам следует помнить о влиянии на многопоточность GUI.

...