.NET CF - Socket.BeginReceive - Выдает ли когда-нибудь SocketException?

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

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

Я предполагаю, что любое SocketException - это канал через EndReceive ().

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

Любые идеи?


person msuhash    schedule 09.02.2012    source источник
comment
Я бы попробовал / поймал это, даже если вы не можете найти причину, по которой это когда-либо могло произойти. Добавление защиты ничего не стоит, и если (я знаю, большое, если) CF когда-либо будет обновлен, или, что более вероятно, если вы повторно используете код на другой платформе, вы останетесь в безопасности.   -  person ctacke    schedule 10.02.2012
comment
@ctacke ты прав. Фактически, я использовал пробную ловушку для всего метода ... просто чтобы охватить ... большинство возможностей.   -  person msuhash    schedule 10.02.2012


Ответы (2)


Я просмотрел справочный источник .NET, и он выдаст исключение.

Код:

[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:

Как заявлено ОП

Это начало приема

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 для ReceiveAsyncRequestcalls 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, исключение будет просто сгенерировано и уничтожит приложение.

person Brad Semrad    schedule 09.02.2012
comment
Не уверен, что это то же самое для сокетов .NET Compact Framework? - person msuhash; 10.02.2012
comment
@msuhash Я не могу сказать наверняка, но копаясь глубже в коде .NET, ошибка возникает из-за вызова библиотек Win32. Это коды ошибок Windows Native Socket, и на 99,9% они будут одинаковыми на всех платформах. Выложу обновленный код местоположения. - person Brad Semrad; 10.02.2012

@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.

Спасибо,

person msuhash    schedule 10.02.2012
comment
посмотрите на мой ответ, я отредактировал его, чтобы включить CF. Это вызывает исключение, вам просто нужно следовать коду. Мне потребовалось некоторое время, чтобы осознать это. - person Brad Semrad; 15.02.2012
comment
Я согласен, но разве это исключение SocketException не происходит внутри пула потоков. Следовательно, потребитель получает это исключение в момент вызова EndReceive? - person msuhash; 17.02.2012
comment
Внизу добавлено больше об этом. - person Brad Semrad; 17.02.2012
comment
@Brad - Думаю, ты прав. (см. это - social. msdn.microsoft.com/Forums/en-GB/ncl/thread/). Спасибо за помощь! - person msuhash; 20.02.2012