【问题标题】:The asynchronous method starts AsyncCallback in the current thread (main thread)异步方法在当前线程(主线程)启动AsyncCallback
【发布时间】:2018-03-27 16:53:20
【问题描述】:

有一个 TcpListener 类的服务器。它使用 BeginAcceptTcpClient (AsyncCallback, Object) 方法接受传入连接。

代码写在示例MSDN中

public static ManualResetEvent tcpClientConnected = 
    new ManualResetEvent(false);

public static void DoBeginAcceptTcpClient(TcpListener 
    listener)
{
    while(true)
    {
        tcpClientConnected.Reset();
        Console.WriteLine("Waiting for a connection...");
        listener.BeginAcceptTcpClient(
            new AsyncCallback(DoAcceptTcpClientCallback), 
            listener);
        tcpClientConnected.WaitOne();
    }
}
public static void DoAcceptTcpClientCallback(IAsyncResult ar) 
{
    TcpListener listener = (TcpListener) ar.AsyncState;
    TcpClient client = listener.EndAcceptTcpClient(ar);
    Console.WriteLine("Client connected completed");
    tcpClientConnected.Set();
    while(true)
    {
         //Receiving messages from the client
    }
}

问题在于 DoAcceptTcpClientCallback (IAsyncResult ar) 方法有时 开始在当前线程 (main) 中执行,而不是在新线程中执行,并阻塞它 (main)。因此,无法接收以下连接。 请帮助理解为什么不为此方法创建一个线程

【问题讨论】:

  • 您没有向我们展示,但我想//Receiving messages from the client 出于某种原因切换回使用 同步 API 调用。不要那样做。一旦你去异步(以某种不涉及创建线程的方式)你不知道你将在哪个线程上运行 - 所以你应该只运行你调度下一个异步方法和然后返回。
  • 首先,你为什么不使用AcceptTcpClientAsync ?它适用于所有受支持的 .NET 版本,使异步编程变得更加容易。
  • 第二个asynchronous 不代表different thread。这意味着您的线程不会阻塞等待响应。 IO 操作甚至可能不需要单独的线程,因为 Windows 中的 IO 在驱动程序级别始终是异步的。 API 模拟阻塞,使单线程编程更容易

标签: c# .net multithreading sockets asynchronous


【解决方案1】:

是的,正如您所发现的,you're not guaranteed that your AsyncCallback is called on a new thread。基本上,如果一个异步操作完成得如此之快,以至于回调可以从同一个线程同步运行,它就会。

BeginXXX 调用想要在旧的异步模型中返回时,您正在等待发生的事情已经发生,例如在您的情况下是一个连接,因此为了防止不必要的上下文切换,它将 IAsyncResult.CompletedSynchronously 设置为 true 并同步执行您的回调,在您的示例中无限阻塞 while (true) 循环中的线程,永远不会让它从 BeginAcceptTcpClient 返回打电话。

您应该在回调方法中考虑这种情况,继续保持异步并快速返回。

另外,请考虑使用async/await,它们使异步编程更容易。

【讨论】:

    猜你喜欢
    • 2013-07-13
    • 1970-01-01
    • 2023-02-15
    • 2021-06-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多