.NET CF - Socket.BeginReceive - 这会抛出SocketException吗?

时间:2012-02-09 21:35:21

标签: .net sockets compact-framework

我一直在研究如何在.NET CF套接字上调用BeginReceive可以按http://msdn.microsoft.com/en-us/library/dxkwh6zw(v=vs.90).aspx抛出SocketException?

我查看了反射器,但我看不出这是怎么回事?我认为SocketException只有在实际在线程池线程中完成工作时才有可能。

我的猜测是任何SocketException都是通过EndReceive()的通道。

我有一个调用自身的回调方法(即BeginReceive(..,..,回调),它包含一个EndReceive。我想确保在正确的位置添加一个Try-catch。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

我查看了.NET Reference Source,它会抛出异常。

代码:

[HostProtection(ExternalThreading=true)] 
    public IAsyncResult BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state)
    { 
        SocketError errorCode;
        IAsyncResult result = BeginReceive(buffer, offset, size, socketFlags, out errorCode, callback, state);
        if(errorCode != SocketError.Success && errorCode !=SocketError.IOPending){
            throw new SocketException(errorCode); 
        }
        return result; 
    } 

在一个名为DoBeginReceive的方法中从Begin的重载调用的方法中,此方法调用此代码。错误代码使用out关键字传递,因此它正是传回的内容。

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

编辑:对于.NET CF:

由OP指出

这是Begin Receive

public IAsyncResult BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state)
{
    this.throwIfDisposed();
    if (buffer == null)
    {
        throw new ArgumentNullException("buffer");
    }
    if (offset < 0)
    {
        throw new ArgumentOutOfRangeException("offset");
    }
    if (size < 0)
    {
        throw new ArgumentOutOfRangeException("size");
    }
    if (buffer.Length < (offset + size))
    {
        throw new ArgumentOutOfRangeException("", SR.GetString(0x41, new object[0]));
    }
    ReceiveAsyncRequest req = new ReceiveAsyncRequest(this, buffer, offset, size, socketFlags, callback, state);
    this.addReadRequest(req);
    return req;
}

addReadRequest执行此操作:

private void addReadRequest(AsyncRequest req)
{
    lock (this)
    {
        if (this.m_readHead == null)
        {
            if (!startWorker(req))
            {
                req.InvokeCallback(false, new OutOfMemoryException(SR.GetString(0x42, new object[0])));
            }
            else
            {
                this.m_readHead = req;
            }
        }
        else
        {
            AsyncRequest readHead = this.m_readHead;
            while (readHead.m_next != null)
            {
                readHead = readHead.m_next;
            }
            readHead.m_next = req;
        }
    }
}

startWorker执行此操作:

private static bool startWorker(AsyncRequest req)
{
    WorkerThread thread = new WorkerThread(req);
    if (!ThreadPool.QueueUserWorkItem(new WaitCallback(thread.doWorkI)))
    {
        return false;
    }
    return true;
}

Thread调用ReceiveAsyncRequest的doWork调用ReceiveAsyncRequest的doRequest,调用handleRequest,handleRequest又调用ReceiveAsyncRequest上的doRequest。

ReceiveAsyncRequest方法的doRequest如下所示:

protected override object doRequest()
{
    return base.m_socket.ReceiveNoCheck(this.m_readBuffer, this.m_index, this.m_size, this.m_flags);
}

在ReceiveFromNoCheck中,它抛出异常:

internal int ReceiveFromNoCheck(byte[] buffer, int index, int request, SocketFlags flags)
{
    this.throwIfDisposed();
    int rc = 0;
    int num2 = OSSOCK.recv(this.handle, buffer, index, request, (int) flags, ref rc);
    if(num2 < 0)
    {
        throw new SocketException(rc);
    }
    return num2;
}

如果AsyncResults运行sychronously,它将抛出异常。但是,如果它是ThreadPool的一部分,则抛出异常并kill the application

答案 1 :(得分:0)

@Brad

这就是我在.NET CF中看到的。我同意你对完整框架的分析。

以下是CF。

(1)


public IAsyncResult BeginReceive(byte[] buffer, int offset, int size, SocketFlags socketFlags, AsyncCallback callback, object state)
{
    this.throwIfDisposed();
    if (buffer == null)
    {
        throw new ArgumentNullException("buffer");
    }
    if (offset < 0)
    {
        throw new ArgumentOutOfRangeException("offset");
    }
    if (size < 0)
    {
        throw new ArgumentOutOfRangeException("size");
    }
    if (buffer.Length < (offset + size))
    {
        throw new ArgumentOutOfRangeException(null, SR.GetString(0x44, new object[0]));
    }
    ReceiveAsyncRequest req = new ReceiveAsyncRequest(this, buffer, offset, size, socketFlags, callback, state);
    this.addReadRequest(req);
    return req;
}

(2)

private void addReadRequest(AsyncRequest req)
{
    lock (this)
    {
        if (this.m_readHead == null)
        {
            if (!startWorker(req))
            {
                req.InvokeCallback(false, new OutOfMemoryException(SR.GetString(0x45, new object[0])));
            }
            else
            {
                this.m_readHead = req;
            }
        }
        else
        {
            AsyncRequest readHead = this.m_readHead;
            while (readHead.m_next != null)
            {
                readHead = readHead.m_next;
            }
            readHead.m_next = req;
        }
    }
}

 

“startWorker”只是在线程池线程中对项目进行排队。

(3)

private static bool startWorker(AsyncRequest req)
{
    WorkerThread thread = new WorkerThread(req);
    if (!ThreadPool.QueueUserWorkItem(new WaitCallback(thread.doWorkI)))
    {
        return false;
    }
    return true;
}

可能是我的眼睛正在玩游戏,但我无法发现SocketException。

谢谢,