Основной (string [] args) метод не вызван - PullRequest
1 голос
/ 03 апреля 2019

Я использую Visual Studio 2017.

Всякий раз, когда я нажимаю F5, чтобы начать отладку моей программы, я замечаю, что метод Main(string[] args) внутри класса Program не вызывается, даже если полявнутри Program инициализируются, как вы можете видеть на скриншоте ниже:

enter image description here

После создания экземпляра TcpClient и последующего его присвоенияВ соответствующем поле отладчик никогда не достигает точки останова, которую я установил для метода Main(string[] args).

Просто чтобы быть уверенным, я установил объект запуска для своего проекта как класс Program.Это не решило проблему:

enter image description here

Чего мне не хватает?

РЕДАКТИРОВАТЬ:

Я добавил Console.WriteLine("Entering Main method...") в свой метод Main, но он не выводится на консоль, когда я начинаю отладку.

Буквально ничего (точнее, ничего сразу не видно) не происходит после TcpClient экземпляр создан - исключений нет;программа не заканчивается самостоятельно;консоль остается пустой.

РЕДАКТИРОВАТЬ:

Оказывается, происходит сбой в конструкторе TcpClient.

Ответы [ 2 ]

5 голосов
/ 03 апреля 2019

Помните, что конструктор TcpClient(string, int) открывает новое соединение, в этот момент ( doc ):

Инициализирует новый экземпляр класса TcpClient и подключается к указанному порту на указанном хосте.
...
Этот конструктор создает новый TcpClient и выполняет попытку синхронного подключения к указанному имени хоста и номеру порта.

Если я копирую / вставляю ваш код (вставляя свой собственный RemoteServerIpAddressString), то я вижу, что приложение зависает при попытке создать TcpClient. Если в тот момент я сломаю отладчик, я вижу, что он застрял в System.Net.Sockets.Socket.DoConnect, который пытается подключиться к удаленному компьютеру.

Через некоторое время он сдается, выдает исключение, и выдается TypeInitializationException, что прерывает отладчик.

Это соответствует вашему наблюдению:

Буквально ничего (точнее, ничего сразу не видимого) не происходит после создания экземпляра TcpClient - исключений нет; программа не заканчивается самостоятельно; консоль остается пустой.

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

Если я убедился, что TcpClient подключается к открытому порту, тогда конструктор TcpClient сразу завершается, и Main запускается.


Это очень плохая идея - делать длительные вещи, особенно сетевые, внутри статического конструктора. CLR должен получить блокировку при инициализации типа, и это мешает инициализации других типов и может вызвать взаимные блокировки.

Возможно, вы захотите либо создать TcpClient внутри вашего Main метода, либо создать его как:

private static readonly TcpClient TcpClient = new TcpClient();

и затем в основном:

TcpClient.Connect(...);
1 голос
/ 03 апреля 2019

Инициализаторы статического поля в этом случае (класс Program) не должны содержать код, который может выдать или истекло время ожидания.

Код, выделенный в вопросе, является инициализатором статического поля. Он будет запущен при первом обращении к типу, перед любым статическим методом или даже статическим конструктором . Если инициализаторы или статический конструктор заблокируют или выбросят, приложение будет завершено без вызова Main. Это означает, что для обработки этих исключений нельзя использовать код обработки ошибок.

Этот гарантированный порядок делает реализацию простых синглетонов в C # очень легкой. Двойная блокировка не требуется, поскольку порядок выполнения гарантирован. Прочтите статью Джона Скита о реализации Singleton :

public sealed class Singleton
{
    private static readonly Singleton instance = new Singleton();

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()    {    }
    private Singleton()   {    }

    public static Singleton Instance
    {
        get 
        {
            return instance;
        }
    }
}

Этого достаточно, чтобы создать потокобезопасный синглтон

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