2016-12-02 6 views
1

Я извлекаю из класса System.Net.HttpClient для реализации клиента, который обрабатывает извлечение токенов и обновление. Клиент инициализируется с использованием всех необходимых параметров аутентификации и может потенциально использоваться одновременно. В этом случае мне нужно запретить клиенту запрашивать несколько токенов (для разных запросов).Может ли использование Семафора в асинхронных методах привести к взаимоблокировкам в потоке диспетчера WPF?

Я не уверен, может ли мой код привести к тупиков в приложении WPF, если пользователь запускает несколько веб-запросов на диспетчерском нити (поскольку семафор неповторно, поэтому диспетчеру нить может быть заблокирован во время ожидания на семафоре, и исходная задача может не завершиться, если поток диспетчера заблокирован).

public class ApiClient : HttpClient 
{ 
    public override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     if (_token == null) 
     { 
      await _semaphore.WaitAsync(cancellationToken); 
      try 
      { 
       if (_token == null) 
       { 
        // _token = await _tokenService.AcquireToken(xx,xx,xx); 
       } 
      } 
      finally 
      { 
       _semaphore.Release(); 
      } 
     } 
     else if (_token.IsExpired) 
     { 
      await _semaphore.WaitAsync(cancellationToken); 
      try 
      { 
       if (_token.IsExpired) 
       { 
        // _token = await _tokenService.RefreshToken(xx,xx,xx); 
       } 
      } 
      finally 
      { 
       _semaphore.Release(); 
      } 
     } 
     return await base.SendAsync(request, cancellationToken); 
    } 
} 
+1

Тупик возникает, когда есть 2 потока, ожидающих друг друга. Поэтому в основном, если ваш Dispatcher Thread ждет Api Thread (что на самом деле происходит) и Api Thread ждут ответа от Dispatcher Thread (это не должно быть так), тогда вы получите тупик. Я не понимаю, почему в вашем сценарии должен произойти тупик. В худшем случае будет тайм-аут, если запросов слишком много, а некоторым не удастся закончить со временем. – 3615

+0

Но я определенно получаю тупик при использовании синхронного метода Wait() семафора, верно? – Ehssan

+1

Я так не думаю. Если вы будете использовать Wait() вместо WaitAsync(), ситуация с взаимоблокировками не должна изменяться, если Api Thread каким-то скрытым способом попытается получить доступ к Dispatcher Thread. Разница была бы более неэффективным использованием потоков: ApplicationPool Task не вернется в пул, если семафор заполнен, но будет заблокирован. Поэтому, когда следующий запрос будет создан, заблокированный поток не сможет обслуживать запрос, и будет создан новый поток. Таким образом, вы получите гораздо больше потоков. – 3615

ответ

0

диспетчеру поток может быть заблокирован во время ожидания на семафоре

Это не может произойти с кодом вы показали. Используется асинхронный ждет (await), поэтому поток не будет заблокирован.