una traves todos subprocesos subproceso seguras requiere realizar que para otro metodo los llamó llamar llamadas interfaz función framework formularios evaluación ejecuten diferente desde controles control como checkforillegalcrossthreadcalls aplicación aplanó acceder c#-4.0 asynchronous udpclient

c# 4.0 - traves - Cómo utilizar la recepción asincrónica para UdpClient en un bucle?



metodo invoke c# (3)

Estoy construyendo una aplicación multiproceso. Uno de los hilos es responsable de procesar los mensajes UDP que provienen de una pieza de hardware externa. Actualmente estoy usando el método UdpClient.Receive en un bucle. Creo que el método de recepción bloquea el hilo mientras espera el siguiente mensaje. Tengo una variable compartida (_isCancelled) que uso si quiero cerrar todos los hilos y detener la aplicación con gracia. Sin embargo, debido a que este método de recepción bloquea, no puedo cerrar la aplicación con elegancia si se ha perdido la comunicación con la pieza de hardware externa. Aquí está el bucle del código actual

UdpClient _client = new UdpClient(8000); IPEndPoint _endPoint = new IPEndPoint(IPAddress.Any, 8000); while (!_isCancelled) { byte[] _bytes = _client.Receive(ref _endPoint); ...process data... }

Estoy pensando que debería usar los métodos de recepción asíncrona. Pero no estoy completamente seguro de entender cómo funcionan y cómo debería estructurar mi código. Quiero poder recibir datos y procesarlos continuamente. Y, en cualquier momento, quiero poder cerrar con gracia el hilo configurando _isCancelled en true. Y si por alguna razón perdemos comunicación con el hardware externo o no recibimos más mensajes, aún deberíamos poder cerrar el hilo.


He agregado un código para demostrar cómo se puede implementar el ciclo utilizando BeginReceive / EndReceive. Esto le muestra una versión simplificada que puede modificar o implementar fácilmente:

UdpClient local; bool stop; public void StartReceiving() { local = new UdpClient(serverIP); Receive(); // initial start of our "loop" } public void StopReceiving() { stop = true; local.Client.Close(); } private void Receive() { local.BeginReceive(new AsyncCallback(MyReceiveCallback), null); } private void MyReceiveCallback(IAsyncResult result) { IPEndPoint ip = new IPEndPoint(IPAddress.Any, 0); local.EndReceive(result, ref ip); if (!stop) { Receive(); // <-- this will be our loop } }

Que te diviertas


Para los métodos más nuevos que usan TAP en lugar del método Begin / End, puede usar lo siguiente en .Net 4.5

¡Bastante sencillo!

Método asincrónico

private static void UDPListener() { Task.Run(async () => { using (var udpClient = new UdpClient(11000)) { string loggingEvent = ""; while (true) { //IPEndPoint object will allow us to read datagrams sent from any source. var receivedResults = await udpClient.ReceiveAsync(); loggingEvent += Encoding.ASCII.GetString(receivedResults.Buffer); } } }); }

Método sincrónico

Como se aplica al método asynchronous anterior, esto también se puede implementar en el método synchronous de una manera muy similar:

private static void UDPListener() { Task.Run(() => { using (var udpClient = new UdpClient(11000)) { string loggingEvent = ""; while (true) { //IPEndPoint object will allow us to read datagrams sent from any source. var remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); var receivedResults = udpClient.Receive(ref remoteEndPoint); loggingEvent += Encoding.ASCII.GetString(receivedResults); } } }); }


Otro enfoque con algún soporte para cancelar. Prefiero la sensación recursiva en el ciclo while(true) .

private async void Listen() { var resp = await _udpClient.ReceiveAsync().ConfigureAwait(false); var eventHandler = PacketReceived; if (eventHandler != null) eventHandler(this, new UdpPacketReceivedEventArgs(resp)); if (_running) Listen(); }