TCPlistener.BeginAcceptSocket — асинхронный вопрос

Некоторое время назад я заплатил программисту за создание многопоточного сервера. Тем временем я немного изучил C #, и теперь я думаю, что вижу проблему замедления - этот парень сказал мне, что в основном потоке (Form) ничего не обрабатывается, поэтому его нельзя заморозить ... но это так. Но я думаю, что хотя BeginAcceptSocket является асинхронной операцией, но ее обратный вызов выполняется в основном потоке, и если есть блокировка, это причина, по которой приложение зависает. Я прав? Спасибо.

    this.mTcpListener.BeginAcceptSocket(this.AcceptClient, null);
  protected void AcceptClient(IAsyncResult ar)
        {
            //some locking stuff
        }

person Mirek    schedule 15.11.2009    source источник


Ответы (5)


Нет, AcceptClient() не будет работать в основном потоке.

Лучше покажи что-нибудь из "замков".

person Henk Holterman    schedule 15.11.2009
comment
Действительно? Я думал, что обратный вызов выполняется в потоке, вызвавшем асинхронную операцию. - person Petr; 16.11.2009
comment
Петр, во-первых: как обратный вызов «вломится» в исходный поток? - person Henk Holterman; 16.11.2009
comment
Да, это правда.. Я почему-то думал, что первый поток ждет, пока не будет вызван обратный вызов... нет асинхронности: D Вы, конечно, правы - person Petr; 16.11.2009

Методы асинхронного ввода-вывода Begin/End используют ThreadPool потоков для выполнения делегата обратного вызова, если операция не может быть завершена мгновенно; в этом случае он выполняется синхронно в вызывающем потоке.

Из Асинхронный вызов синхронных методов:

Передайте делегат для метода обратного вызова в BeginInvoke. Метод выполняется в потоке ThreadPool после завершения асинхронного вызова. Метод обратного вызова вызывает EndInvoke.

Обратный вызов не должен часто происходить в потоке GUI. Если окно приложения перестает отвечать на запросы, это может быть результатом чрезмерного вызова методов в потоке графического интерфейса — обычно для обновления элементов управления.

person Mark    schedule 08.06.2010

Я сделал небольшой тест winapp, и результат заключается в том, что даже если метод «AcceptClient» объявлен в том же классе, чем этот делегат вызывается из другого потока, отличного от основного потока приложения winform, и, следовательно, блокировки НЕТ.

person psulek    schedule 29.04.2010

Каждый раз, когда ваш код получает блокировку, а затем делает что-то, у вас есть кандидат на узкое место, однако поток, вызывающий BeginAcceptSocket, не будет заблокирован и может продолжать работу до тех пор, пока не произойдет событие обратного вызова. До тех пор он не будет выполнять обработчик обратного вызова, поэтому в вашем примере ни одна блокировка не произойдет, пока с ним не свяжется клиент. Он по-прежнему может зависать в коде принятия, если то, что он делает в этот момент, требует времени или задерживается из-за проблем со связью, но из вашего примера кода трудно сказать, так ли это.

person tvanfosson    schedule 15.11.2009
comment
Извините, вы неправильно поняли вопрос. Я спрашивал, прав ли я, что метод AcceptClient работает в основном потоке, а не асинхронно. Поэтому, если есть блокировка, основное приложение (форма) зависнет. - person Mirek; 15.11.2009

Обратный вызов AcceptClient(IAsyncResult ar) может выполняться синхронно.

Я предполагаю, что если BeginAccept обнаружит, что есть новый клиент, он может синхронно выполнить метод обратного вызова.

Чтобы убедиться, что вы должны остановить свое приложение под отладчиком, когда оно зависло, и посмотреть, что делает основной поток (событие).

Как правило, лучше иметь отдельный поток для выполнения любого ввода-вывода.

person Vadym Stetsiak    schedule 11.06.2010