C#:Сбой при ManualResetEvent
-
03-07-2019 - |
Вопрос
Я написал свой код, используя эта статья на сайте msdn в качестве основного помощника
Мой код:
private ManualResetEvent _AllDone = new ManualResetEvent(false);
internal void Initialize(int port,string IP)
{
IPEndPoint _Point = new IPEndPoint(IPAddress.Parse(IP), port);
Socket _Accpt = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_Accpt.Bind(_Point);
_Accpt.Listen(2);
while (true)
{
_AllDone.Reset();
_Accpt.BeginAccept(null, 0, new AsyncCallback(Accept), _Accpt);
_AllDone.WaitOne(); <<crash here
}
}
Вот что происходит, я установил точку останова в BeginAccept (я думал, что в этом проблема), но она выполняет это нормально.Однако, когда я пытаюсь перейти "_AllDone.WaitOne()" - сбой сервера.
Если _allDone не может быть использован в приложении формы win32 - как мне создать свой проект?
Редактировать
Я забыл упомянуть, что я написал _AllDone.Reset() в Accept(), но он туда не попадает, я установил там точку останова, но она не пойдет.
private void Accept(IAsyncResult async)
{
_AllDone.Set();
Socket _Accpt = (Socket)async.AsyncState;
Socket _Handler = _Accpt.EndAccept(async);
StateObject _State = new StateObject();
_State.workSocket = _Handler;
_Handler.BeginReceive(_State.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), _State);
}
Решение
Так что, если я все правильно понял, ты захочешь начать все заново Accept
как только будет получено соединение с сокетом, и не ждать, пока Accept
выполняется, и именно поэтому вы не используете синхронизирующую версию Accept
.
Итак, вы говорите, что он не запускает ваш метод Accept при подключении сокета к указанному адресу и порту?Потому что это то, что делает Accept:он принимает новое входящее соединение, ожидая, пока подключится клиент.Так что, возможно, именно поэтому вы думаете, что он "разбился" и почему он никогда не достигает вашего кода в вашем методе Accept.
Подсказка:может быть, вы также взглянете на Socket.AcceptAsync
Редактировать: Чтобы настроить асинхронный сервер, прослушивающий входящие подключения, вам не нужно никакого ManualWaitEvent:
internal void Initialize(int port,string IP) {
IPEndPoint _Point = new IPEndPoint(IPAddress.Parse(IP), port);
Socket _Accpt = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_Accpt.Bind(_Point);
_Accpt.Listen(2);
_Accpt.BeginAccept(null, 0, new AsyncCallback(Accept), _Accpt);
}
private void Accept(IAsyncResult async) {
Socket _Accpt = (Socket)async.AsyncState;
Socket _Handler;
try {
_Handler = _Accpt.EndAccept(async);
} finally {
_Accpt.BeginAccept(null, 0, new AsyncCallback(Accept), _Accpt);
}
StateObject _State = new StateObject();
_State.workSocket = _Handler;
_Handler.BeginReceive(_State.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), _State);
}
Примечание: Вам также понадобится условие выхода, чтобы BeginAccept не вызывался (например, когда вы хотите завершить работу сервера).
Другие советы
Я думаю, что Lucero пытается сказать, что приложение работает нормально, вы можете спросить, как получилось.
Что ж, когда вы используете серверное приложение с сокетами, то, что вы в основном делаете, это просите сервер подключиться к порту и ждете прибытия соединения.когда приходит соединение, вы выполняете остальную часть кода.
Что имел в виду Лусеро, так это то, что пока на сервер не поступает никаких сообщений, сервер продолжает запрашивать и ждать, что может выглядеть для вас так, как будто оно зависает.
Так ли это в вашем коде?