I am using Visual Studio 2017.
Whenever I press F5
to start debugging my program, I notice that the Main(string[] args)
method inside the Program
class is not called, even though the fields inside Program
are initialized, as you can see from the screenshot below:
After creating a TcpClient
instance and then assigning it to the corresponding field, the debugger never hits the breakpoint I have set on the Main(string[] args)
method.
Just to be sure, I have set the startup object for my project to be the Program
class. That did not fix the issue:
What am I missing?
EDIT:
I have added Console.WriteLine("Entering Main method...")
inside my Main
method, but it is not printed to the console when I start debugging.
Literally nothing (or rather, nothing immediately visible) happens after the TcpClient
instance is created -- no exceptions thrown; the program doesn't self-terminate; the console stays blank.
EDIT:
Turns out a crash is occurring inside the TcpClient
constructor.
Remember that the TcpClient(string, int)
constructor opens a new connection, at that point (doc):
Initializes a new instance of the TcpClient class and connects to the specified port on the specified host.
...
This constructor creates a new TcpClient and makes a synchronous connection attempt to the provided host name and port number.
If I copy/paste your code (inserting my own RemoteServerIpAddressString
), then I see the application hang as it tries to construct the TcpClient
. If I break the debugger at that point, I can see that it's stuck in System.Net.Sockets.Socket.DoConnect
, which is trying to connect to the remote machine.
After a while it gives up, throws an exception, and a TypeInitializationException
gets thrown, which breaks the debugger.
This matches your observation:
Literally nothing (or rather, nothing immediately visible) happens after the TcpClient instance is created -- no exceptions thrown; the program doesn't self-terminate; the console stays blank.
At this point, the TcpClient
is still trying to connect. Until it succeeds, the type never gets initialized, and until this happens Main
will never be run. If you leave it long enough it will probably fail, just as mine did.
If I make sure that the TcpClient
is connecting to a port which is open, then the TcpClient
constructor completes straight away and Main
runs.
It's a very bad idea to do long-running things - especially network-y things - inside a static constructor. The CLR needs to acquire a lock when a type is being initialized, and this stops other types from being initialized, and can cause deadlocks.
You probably want to either construct the TcpClient
inside your Main
method, or construct it as:
private static readonly TcpClient TcpClient = new TcpClient();
and then in main:
TcpClient.Connect(...);