web-dev-qa-db-fra.com

Verrouillage asynchrone non autorisé

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 ...)

18
Philippe Paré

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();
    }
}
45
Jared Moore

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.

13
Contango