Fondamentalement, je veux faire plusieurs demandes asynchrones à un serveur TCP. J'ai actuellement un client qui est uniquement synchrone et bloque l'interface utilisateur à chaque appel réseau. Étant donné que plusieurs demandes peuvent se produire presque en même temps, j'ai essayé de le faire:
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;
}
}
Je suis sûr que ce n'est pas une bonne utilisation de la serrure, mais c'est la seule façon dont je peux penser qui pourrait faire attendre les appels. Y a-t-il un objet que je peux utiliser pour obtenir ce genre de comportement? Je pensais que Monitor serait le même, donc je n'ai pas essayé (je comprends que ce sont des trucs multithreads mais c'est tout ce que je connais ...)
Le problème que vous rencontrez est que les threads se bloqueront lors de l'acquisition du verrou, donc votre méthode n'est pas complètement asynchrone. Pour résoudre ce problème, vous pouvez utiliser 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();
}
}
Ce problème a été parfaitement résolu par le package NuGet Nito.AsyncEx
qui compte plus de 50 000 téléchargements en août 2015.
De ReadMe:
AsyncEx Une bibliothèque d'assistance pour async/wait.
Prend en charge .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 et toutes ses bibliothèques portables.
[couper]
AsyncLock
De nombreux développeurs commencent à utiliser cette bibliothèque pour AsyncLock, un mécanisme d'exclusion mutuelle compatible async. L'utilisation d'AsyncLock est simple:
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)); } }
Voir le code source C # sur GitHub ou installer le package NuGet Nito.AsyncEx
.