亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

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

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

C#
蕭十郎 2022-11-22 16:40:37
我正在使用 Visual Studio 2017。每當我按下F5開始調試我的程序時,我注意到類Main(string[] args)內部的方法Program沒有被調用,即使內部的字段Program已經初始化,如下面的屏幕截圖所示:創建TcpClient實例并將其分配給相應的字段后,調試器永遠不會命中我在Main(string[] args)方法上設置的斷點??梢钥隙ǖ氖?,我已將項目的啟動對象設置為Program該類。那沒有解決問題:我錯過了什么?編輯:我已經Console.WriteLine("Entering Main method...")在我的Main方法中添加了,但是當我開始調試時它沒有打印到控制臺。TcpClient在創建實例之后,幾乎沒有任何事情(或者更確切地說,沒有立即可見的事情)發生——沒有拋出異常;該程序不會自行終止;控制臺保持空白。編輯:結果是構造函數內部發生了崩潰TcpClient。
查看完整描述

3 回答

?
梵蒂岡之花

TA貢獻1900條經驗 獲得超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(...);


查看完整回答
反對 回復 2022-11-22
?
智慧大石

TA貢獻1946條經驗 獲得超3個贊

本例中的靜態字段初始值設定項(Program 類)不應包含可能拋出或超時的代碼。

問題中突出顯示的代碼是靜態字段初始值設定項。這將在第一次訪問類型時運行,在任何靜態方法甚至靜態構造函數之前運行。如果初始值設定項或靜態構造函數阻塞或拋出,應用程序將終止而不調用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;

        }

    }

}

這足以創建一個線程安全的單例


查看完整回答
反對 回復 2022-11-22
?
qq_笑_17

TA貢獻1818條經驗 獲得超7個贊

我正在添加一個新的答案,因為我在隱藏類加載和其他初始化異常的更復雜的托管環境中遇到了類似的問題。


為了解決這個問題,我這樣做了:


將我的Main方法重命名為Main2,因此它不會與下一個更改沖突。

創建了另一個 Program 類,這次是干凈的,它調用Main2,如下所示:

class CleanProgram {


    static void Main(string[] args) {

        try {

            Program.Main2(args);

        } catch (Exception ex) {

            Console.WriteLine("{0}", ex);

        }

    }


}

上面的更改僅用于診斷目的!找到并解決問題后,可以撤消更改。


查看完整回答
反對 回復 2022-11-22
  • 3 回答
  • 0 關注
  • 142 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號