SocketAsyncEventArgs.Completed doesn't fire in Windows 8

匿名 (未验证) 提交于 2019-12-03 08:54:24

问题:

When I compile this code on a machine with Windows 7 Ultimate and .NET 4 installed, it works just fine but when I try it on one with Windows 8 RTM and .NET 4.5 installed, Complete event never fires.

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);     } } 

The interesting thing here is if I put a breakpoint at this line and debug it:

var arguments = new SocketAsyncEventArgs(); 

And connect this server using Hercules before continuing execution, it works like a charm. I do this at the start and then magically, OnAccepted gets called and writes "Accepted." to the console on every single connection. I use the same code and same program (Hercules) on the machine with Windows 7 and .NET 4 but it always works.

  • Am I doing something wrong?
  • If not, is it a known bug of my OS or .NET Framework version 4.5?
  • Can anyone reproduce this?

Edit: Both operating systems are 64 bit.
Edit 2: I reported this as a bug on Microsoft Connect, here.
Edit 3: Found a workaround and post it to Connect (Simply by creating a fake, first connection).
Edit 4: If anyone can reproduce this, please join the issue in Connect.
Edit 5: I saw the question Thomas has mentioned and I tested whether Console.ReadLine was causing this or not. Turned out it was. If I add Thread.Sleep(3000) before my Console.ReadLine call and make a connection attempt in 3 seconds after I run the program, it works like a charm. Again, the odd thing is that I need to do this only once before calling Console.ReadLine. If I make one connection before calling Console.ReadLine then every consecutive connection works, even after Console.ReadLine is called. I'll mention this in the Conect page.
Edit 6: I added the link to the other question to the Connect page and added another workaround that involves calling Thread.Sleep before calling Console.ReadLine like I mentioned in the above edit.

回答1:

It turned out to be a Windows 8 bug. Best workaround I could find so far is to start the IOCP operation on a different thread.

So the thing I should do in the code sample that is given in the question is changing this line:

Accept(arguments); 

To this line in the Main method:

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

This prevents Console.ReadLine() call to block the IOCP operation.

As a side note: This is just a workaround to an operating system bug which will most likely be fixed via an update and -hopefully- making this workaround redundant.

This issue is fixed with the latest version of Windows 8.


Edit: Status of the feedback item I have posted in Connect is changed to "By Design".
I also received an e-mail which contains the following:

The underlying issue for this behavior has to do with how IO Completion Ports are handled in Windows 8. .NET works using the completion ports; when their behavior changed, so did the .NET behavior.

Edit 2: Status of the feedback is changed again to "Active" with no details.

Edit 3: The feedback received another answer from Microsoft, stating:

The latest version of Windows 8 should have this fixed. Note that it's an OS issue, not a .NET issue: you need to make sure you have the latest version of the OS. No changes were made to .NET to either cause or fix this issue."



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!