2012-08-27 32 views
4

當我在安裝了Windows 7 Ultimate和.NET 4的機器上編譯此代碼時,它工作得很好,但是當我在Windows 8 RTM和.NET 4.5上試用時安裝,完整的事件永遠不會觸發。SocketAsyncEventArgs.Completed在Windows 8中不啓動

class Program 
{ 
    private static Socket _Socket = new Socket(
     AddressFamily.InterNetwork, 
     SocketType.Stream, 
     ProtocolType.Tcp); 

    private static void Main(string[] args) 
    { 
     _Socket.Bind(new IPEndPoint(IPAddress.Any, 5012)); 
     _Socket.Listen(100); 

     var arguments = new SocketAsyncEventArgs(); 
     arguments.Completed += OnAccepted; 
     Accept(arguments); 

     Console.ReadLine(); 
    } 

    private static void Accept(SocketAsyncEventArgs args) 
    { 
     args.AcceptSocket = null; 
     if (!_Socket.AcceptAsync(args)) 
      OnAccepted(null, args); 
    } 

    private static void OnAccepted(object sender, SocketAsyncEventArgs e) 
    { 
     Console.WriteLine("Accepted."); 
     Accept(e); 
    } 
} 

這裏有趣的是,如果我把一個斷點在該行並調試它:

var arguments = new SocketAsyncEventArgs(); 

,並繼續執行之前連接使用Hercules這臺服務器,它的工作原理就像一個魅力。我在開始時這樣做,然後神奇地,OnAccepted被調用並寫入「Accepted」。到每一個連接上的控制檯。我在Windows 7和.NET 4的機器上使用相同的代碼和相同的程序(Hercules),但始終有效。

  • 我做錯了什麼?
  • 如果不是,它是我的操作系統或.NET Framework版本4.5的已知錯誤?
  • 任何人都可以重現嗎?

編輯:兩個操作系統都是64位。
編輯2:我報告這是Microsoft Connect上的一個錯誤,here
編輯3:找到解決方法並將其發佈到Connect(僅通過創建假的第一個連接)。
編輯4:如果任何人可以重現此問題,請在Connect中加入問題。
編輯5:我看到了question Thomas has mentioned,我測試了Console.ReadLine是否導致這個問題。原來是這樣。如果我在之前添加Thread.Sleep(3000)我的Console.ReadLine調用並在運行該程序後3秒內進行連接嘗試,它就像一個魅力。再一次,奇怪的是,我只需要調用Console.ReadLine之前只做一次。如果我在撥打Console.ReadLine之前建立一個連接,那麼即使在調用Console.ReadLine之後,每個連續的連接都可以工作。我會在Conect頁面中提到這一點。
編輯6:我向鏈接頁面添加了其他問題的鏈接,並添加了另一個解決方法,在調用Console.ReadLine之前調用Thread.Sleep,就像我在上面的編輯中提到的那樣。

+0

您是否檢查過這不僅僅是防火牆/ etc的東西?它是否適用於Socket.Accept?(我的觀點是:是問題與AcceptAsync,或與網絡通常?) –

+0

@Marc:接受的作品。AcceptAsync也可以,但只有當我嘗試連接_before_調用AcceptAsync。奇怪的是,這樣做修復everyting。所有後續連接工作沒有問題如果我在Listen之後和AcceptAsync之前放置了一個斷點,當執行停止時,我只需使用Hercules連接到該套接字,然後按F5:Bang,隨後的每個連接就像一個魅力一樣。 –

+0

我不清楚一件事, 「Completed」從不觸發的情況下,OnAccept仍被調用? –

回答

1

原來是Windows 8的一個bug。目前爲止找到的最佳解決方法是在不同的線程上啓動IOCP操作。

所以我應該是在問題中給出的代碼示例中要做的就是改變這一行:

Accept(arguments); 

這條線在Main方法:

Task.Run(() => Accept(arguments)).Wait(); 

這可以防止Console.ReadLine()調用來阻止IOCP操作。

附註:這只是一個解決操作系統錯誤的方法,它很可能通過更新修復,並且 - 很高興 - 使此解決方法變得冗餘。

這個問題是固定的


編輯的Windows 8的

最新版:feedback item I have posted in Connect狀態更改爲「按設計」。
我也收到一封電子郵件,其包含以下內容:

對這種現象的根本問題是與IO 完成端口是如何在Windows 8的.NET工程使用 完成端口處理做的;當他們的行爲發生變化時,.NET 行爲也發生了變化。

編輯2:反饋的狀態再次更改爲「活動」,沒有任何詳細信息。

編輯3:反饋收到另一個答案來自微軟,他說:

的Windows 8的最新版本應該有這個固定的。請注意,這是一個操作系統問題,而不是.NET問題:您需要確保您擁有最新版本的操作系統。沒有對.NET進行任何更改,以導致或解決此問題。「

+1

是否有任何人可以公開跟蹤的官方Microsoft bug報告? –

+0

@mizi_sk:我找不到。我發現了[此Tec​​hNet論壇帖子]中提到的MS Connect鏈接(http://social.technet.microsoft.com/Forums/en-US/winserver8gen/thread/5764cd0f-fda1-4cfa-ae35-808210bae77e),但它不再工作了。在同一頁中,Len Holgate評論了微軟的迴應:「我們已經將這個通知交給了基礎操作系統團隊,他們會考慮將來的更新,我正在解決這個問題。」所以沒有確切的日期或活動的錯誤報告來跟蹤afaik。 –

+0

這是不幸的...謝謝 –