从Async Callback调用Sync方法调用?

时间:2015-06-22 12:19:02

标签: c# asynchronous synchronous

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

示例:

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

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

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

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

2 个答案:

答案 0 :(得分:2)

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

别忘了给EndReceive打电话。

另请注意,由于await,APM模式已过时。可能你应该转换。

答案 1 :(得分:2)

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

如果您有兴趣,可以在source code中看到。此特定方法适用于Socket类(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);
    }
}