'Main(string[] args) method not called
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.
Solution 1:[1]
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(...);
Solution 2:[2]
Static field initializers in this case (the Program class) shouldn't contain code that may throw or time out.
The code highlited in the question is a static field initializer. This will run the first time a type is accessed, before any static method or even the static constructor. If the initializers or the static constructor block or throw, the application will terminated without calling Main. This means that no error handling code can be used to catch those exceptions.
This guaranteed order makes implementing simple singletons in C# very easy. No double locking is needed as the order of execution is guaranteed. Check Jon Skeet's article on Singleton implementation :
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;
}
}
}
That's enough to create a thread-safe singleton
Solution 3:[3]
I'm adding a new answer because I hit a similar issue in a more complex hosting environment that was hiding class load and other initialization exceptions.
In order to catch the issue, I did this:
- Renamed my
Mainmethod toMain2, so it does not conflict with the next change. - Created another Program class, clean this time, that calls
Main2, like the one below:
class CleanProgram {
static void Main(string[] args) {
try {
Program.Main2(args);
} catch (Exception ex) {
Console.WriteLine("{0}", ex);
}
}
}
The change above is only for diagnostics purposes! After you find and fix the problem, the change can be undone.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | fernacolo |


