Асинхронная блокировка не разрешена

По сути, я хочу сделать несколько асинхронных запросов к tcp-серверу. В настоящее время у меня есть работающий клиент, который работает только синхронно и блокирует пользовательский интерфейс при каждом сетевом вызове. Поскольку несколько запросов могут возникать практически одновременно, я попытался сделать это:

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;
    }
}

Я уверен, что это не очень хорошее использование блокировки, но я думаю, что это единственный способ заставить звонки ждать своей очереди. Есть ли объект, который я могу использовать для достижения такого поведения? Я думал, что Monitor будет таким же, поэтому я не пытался (я понимаю, что они многопоточные вещи, но это все, что я знаком с ...)

12 голосов | спросил Philippe Paré 19 AM00000040000001331 2015, 04:08:13

2 ответа


0

Похоже, проблема в том, что потоки будут блокироваться при получении блокировки, поэтому ваш метод не является полностью асинхронным. Чтобы решить эту проблему вы можете использовать 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
    try
    {
        await readLock.WaitAsync();
        Details details = await connection.GetDetailsAsync();
        detailsListBox.Items = details;
    }
    finally
    {
        readLock.Release();
    }
}
ответил Jared Moore 19 AM00000040000000831 2015, 04:21:08
0

Эта проблема была аккуратно решена с помощью пакета NuGet Nito.AsyncEx, который по состоянию на август 2015 года загружен более 50 000 раз.

Из ReadMe:

  

AsyncEx. Вспомогательная библиотека для async /await.

     

Поддерживает .NET 4.5 /4.0, iOS, Android, Windows Store 8.0, Windows Phone   Silverlight 8.0 /7.5, приложения для Windows Phone 8.1, Silverlight   5.0 /4.0 и все их переносимые библиотеки.

     

[надрез]

     

AsyncLock

     

Многие разработчики начинают использовать эту библиотеку для AsyncLock, асинхронно-совместимого механизма взаимного исключения. Использовать AsyncLock просто:

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));
  }
}

Смотрите исходный код C # на GitHub или установите пакет NuGet Nito.AsyncEx

ответил Contango 21 PM000000120000005831 2015, 12:30:58

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132