SocketAsyncEventArgs.Completed 在 Windows 8 中不会触发

Posted

技术标签:

【中文标题】SocketAsyncEventArgs.Completed 在 Windows 8 中不会触发【英文标题】:SocketAsyncEventArgs.Completed doesn't fire in Windows 8 【发布时间】:2012-08-27 15:59:12 【问题描述】:

当我在安装了 Windows 7 Ultimate 和 .NET 4 的机器上编译此代码时,它工作得很好,但是当我在安装了 Windows 8 RTM 和 .NET 4.5 的机器上尝试它时,永远不会触发 Complete 事件。

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 之后,每个连续的连接都有效。我将在连接页面中提到这一点。编辑 6:我将另一个问题的链接添加到连接页面,并添加了另一个解决方法,涉及在调用 Console.ReadLine 之前调用 Thread.Sleep就像我在上面的编辑中提到的那样。

【问题讨论】:

你检查过这不仅仅是防火墙/等等吗?它适用于 Socket.Accept 吗? (我的意思是:AcceptAsync 有问题,还是一般网络有问题?) @Marc:接受作品。 AcceptAsync 也可以工作,但前提是我尝试在调用 AcceptAsync 之前连接 。奇怪的是这样做可以解决所有问题。如果我只是在 Listen 之后和 AcceptAsync 之前放置一个断点,那么所有后续连接都可以正常工作。当执行停止时,我只是使用 Hercules 连接到该套接字并按 F5:Bang,随后的每个连接都像一个魅力。 我不清楚一件事,在 Completed 从不触发的情况下,OnAccept 仍然被调用? @Peter:不。AcceptAsync 返回 true,因此代码不会同步调用 OnAccepted,并且新连接不会触发 Completed 事件,因此在该实例中不会调用 OnAccepted。 我遇到了与此处讨论的相同的问题:***.com/questions/12464185/… 将加入 Microsoft Connect 【参考方案1】:

原来是 Windows 8 的错误。到目前为止,我能找到的最佳解决方法是在不同的线程上启动 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:反馈收到了 Microsoft 的另一个答复,指出:

最新版本的 Windows 8 应该已修复此问题。请注意,这是操作系统问题,而不是 .NET 问题:您需要确保您拥有最新版本的操作系统。未对 .NET 进行任何更改以导致或解决此问题。”

【讨论】:

是否有任何人都可以公开跟踪的官方 Microsoft 错误报告? @mizi_sk:我找不到。我找到了this TechNet Forum post 中提到的 MS Connect 链接,但它不再起作用了。在同一页面中,Len Holgate 评论了微软的回应:“我们已将此信息传递给基础操作系统团队,他们将考虑在未来的更新中考虑这一点。我正在解决这个推迟的问题。”所以没有确切的日期或有效的错误报告来跟踪 afaik。 @mizi_sk:他们结案了,说这种行为是设计使然。 @mizi_sk:问题已通过更新到 Windows 8 得到解决。我已经用详细信息编辑了答案。

以上是关于SocketAsyncEventArgs.Completed 在 Windows 8 中不会触发的主要内容,如果未能解决你的问题,请参考以下文章