c# - receivecallback - Bloqueo asíncrono no permitido
tcp ip asynchronous communication c# (2)
Básicamente, quiero hacer múltiples solicitudes asincrónicas a un servidor tcp. Actualmente tengo un cliente que funciona que solo es sincrónico y bloquea la interfaz de usuario en cada llamada de red. Dado que pueden producirse varias solicitudes casi al mismo tiempo, intenté hacer esto:
private object readonly readLock = new object();
public async Task UpdateDetailsAsync()
{
//I want every request to wait their turn before requesting (using the connection)
//to prevent a read call from catching any data from another request
lock (readLock)
{
Details details = await connection.GetDetailsAsync();
detailsListBox.Items = details;
}
}
Estoy seguro de que este no es un buen uso del bloqueo, pero es la única forma en que puedo pensar que podría hacer que las llamadas esperen su turno. ¿Hay algún objeto que pueda usar para lograr este tipo de comportamiento? Pensé que Monitor sería el mismo, así que no lo intenté (entiendo que son cosas de subprocesos múltiples, pero eso es todo con lo que estoy familiarizado ...)
Este problema ha sido resuelto perfectamente por el paquete
Nito.AsyncEx
que tiene más de 50,000 descargas a partir de agosto de 2015.
De Léame:
AsyncEx Una biblioteca auxiliar para async / await.
Admite .NET 4.5 / 4.0, iOS, Android, Windows Store 8.0, Windows Phone Silverlight 8.0 / 7.5, Windows Phone Applications 8.1, Silverlight 5.0 / 4.0 y todas las bibliotecas portátiles de los mismos.
[recorte]
AsyncLock
Muchos desarrolladores comienzan a usar esta biblioteca para AsyncLock, un mecanismo de exclusión mutua compatible con async. Usar AsyncLock es sencillo:
private readonly AsyncLock _mutex = new AsyncLock(); public async Task UseLockAsync() { // AsyncLock can be locked asynchronously using (await _mutex.LockAsync()) { // It''s safe to await while the lock is held await Task.Delay(TimeSpan.FromSeconds(1)); } }
Consulte el
código fuente de C # en GitHub
o instale el paquete
Nito.AsyncEx
.
Parece que el problema que tiene es que los subprocesos se bloquearán al adquirir el bloqueo, por lo que su método no es completamente asíncrono. Para resolver esto, puede usar SemaphoreSlim.WaitAsync
private readonly SemaphoreSlim readLock = new SemaphoreSlim(1, 1);
public async Task UpdateDetailsAsync()
{
//I want every request to wait their turn before requesting (using the connection)
//to prevent a read call from catching any data from another request
await readLock.WaitAsync();
try
{
Details details = await connection.GetDetailsAsync();
detailsListBox.Items = details;
}
finally
{
readLock.Release();
}
}