.NET CF - Socket.BeginReceive - это когда-либо вызывает исключение SocketException? - PullRequest
1 голос
/ 10 февраля 2012

Я смотрел, как вызов BeginReceive для сокета .NET CF может вызвать исключение SocketException согласно http://msdn.microsoft.com/en-us/library/dxkwh6zw(v=vs.90).aspx?

Я посмотрел через Отражатель, но я не вижу, как это возможно? Я думаю, что SocketException возможен только при выполнении работы в потоке потоков.

Полагаю, любое SocketException является каналом через EndReceive ().

У меня есть метод обратного вызова, который вызывает себя (то есть BeginReceive (.., .., callback), который содержит EndReceive. Я хочу убедиться, что я добавляю Try-catch в нужном месте.

Есть идеи?

Ответы [ 2 ]

2 голосов
/ 10 февраля 2012

Я посмотрел на .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; 
    } 

В методе, который вызывается из-за перегрузки Begin в методе с именем DoBeginReceive, этот метод вызывает этот код. Код ошибки передается с использованием ключевого слова out, поэтому это именно то, что передается обратно.

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

РЕДАКТИРОВАТЬ: Для .NET CF:

Как указано в OP

Это начало получения

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;
}

Поток вызывает doWork объекта ReceiveAsyncRequest, вызывает doRequest объекта ReceiveAsyncRequest, который вызывает handleRequest, который, в свою очередь, вызывает doRequest для ReceiveAsyncRequest.

doRequest метода ReceiveAsyncRequest выглядит следующим образом:

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 запускается синхронно , он выдаст исключение. Однако, если он является частью ThreadPool, исключение будет просто выдано и уничтожит приложение .

0 голосов
/ 10 февраля 2012

@ Брэд

Это то, что я вижу в .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 &lt 0)
    {
        throw new ArgumentOutOfRangeException("offset");
    }
    if (size &lt 0)
    {
        throw new ArgumentOutOfRangeException("size");
    }
    if (buffer.Length &lt (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) * * 1 010

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.

Спасибо

...