从异步回调调用同步方法调用?

Call Sync method call from Async Callback?

在异步回调中调用同步方法会发生什么?

示例:

private void AcceptCallback(IAsyncResult AR)
{
    tcp.BeginReceive(ReceiveCallback);
}

private void ReceiveCallback(IAsyncResult AR)
{
    tcp.Send(data);
}

已接受连接并启动异步接收回调。当 tcp 连接接收到数据时,它会调用 receive 回调。

如果调用同步 Send 方法,是否会阻止其他异步回调的发生?
还是所有的异步回调都是相互独立的?

是的,回调是相互独立的。它们在线程池上执行。这样做没有错。混合同步和异步 IO 很好。您可以在那些能给您带来最大好处的地方使用异步 IO(大量等待时间长的地方)。

别忘了调用 EndReceive。

另请注意,由于 await,APM 模式已过时。也许你应该切换。

回调是独立的,因为它们是在线程池 IO 完成工作者上调用的。

如果您有兴趣,可以在 source code 中查看。此特定方法用于 Socket class(TcpClientUdpClient 在内部使用),其中重叠 IO 用于调用回调(请参阅 asyncResult.SetUnmanagedStructures 调用:

private void DoBeginReceiveFrom(byte[] buffer, int offset, 
                                int size, SocketFlags socketFlags,
                                EndPoint endPointSnapshot, SocketAddress 
                                socketAddress, OverlappedAsyncResult asyncResult)
{
    EndPoint oldEndPoint = m_RightEndPoint;
    SocketError errorCode = SocketError.SocketError;
    try
    {
        // Set up asyncResult for overlapped WSARecvFrom.
        // This call will use completion ports on WinNT and Overlapped IO on Win9x.
        asyncResult.SetUnmanagedStructures(
                buffer, offset, size, 
                socketAddress, true /* pin remoteEP*/, 
                ref Caches.ReceiveOverlappedCache);

        asyncResult.SocketAddressOriginal = endPointSnapshot.Serialize();

        if (m_RightEndPoint == null) 
        {
            m_RightEndPoint = endPointSnapshot;
        }

        int bytesTransferred;
        errorCode = UnsafeNclNativeMethods.OSSOCK.WSARecvFrom(
            m_Handle,
            ref asyncResult.m_SingleBuffer,
            1,
            out bytesTransferred,
            ref socketFlags,
            asyncResult.GetSocketAddressPtr(),
            asyncResult.GetSocketAddressSizePtr(),
            asyncResult.OverlappedHandle,
            IntPtr.Zero );

        if (errorCode!=SocketError.Success)
        {
            errorCode = (SocketError)Marshal.GetLastWin32Error();
        }
    }
    catch (ObjectDisposedException)
    {
        m_RightEndPoint = oldEndPoint;
        throw;
    }
    finally
    {
        errorCode = asyncResult.CheckAsyncCallOverlappedResult(errorCode);
    }
}