Main(string [] args)方法未调用

时间:2019-04-03 12:06:18

标签: c# visual-studio visual-studio-2017

我正在使用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 个答案:

答案 0 :(得分:5)

请记住,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 :(得分:1)

在这种情况下,

静态字段初始化程序(程序类)不应包含可能抛出或超时的代码。

问题中突出显示的代码是静态字段初始化程序。这将在第一次访问类型before any static method or even the static constructor时运行。如果初始化程序或静态构造函数阻塞或抛出,则应用程序将终止而不调用Main。这意味着不能使用任何错误处理代码来捕获那些异常。

这种有保证的顺序使得在C#中非常简单地实现简单的单例。不需要双重锁定,因为可以保证执行顺序。查看乔恩·斯基特(Jon Skeet)在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;
        }
    }
}

足以创建一个线程安全的单例