1

Мне нужна помощь. В вызове службы веб-api мне нужно вызвать функцию в dll, которая выполняется асинхронно, а затем дает ответ в функции обратного вызова. Теперь, как правило, это было бы хорошо, но теперь с помощью web api идея состоит в том, чтобы выполнить команду, а затем вернуть ответ.Могу ли я избавиться от этого ужасного блокирующего кода?

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

[HttpGet] 
    public HttpResponseMessage Off(string id) 
    { 
     APNLink.Link link = LinkProvider.getDeviceLink(id, User.Identity.Name); 

     if (link.LinkConnectionStatus == APNLink.ConnectionStatus.Connected) 
     { 
      link.RelayCommand(APNLink.RelayNumber.Relay1, APNLink.RelayCommand.OFF, test); 
      BlockForResponse(); 
      var msg = Request.CreateResponse(HttpStatusCode.OK); 
      return msg; 
     } 
     else 
     { 
      if (link.Connect()) 
      { 
       var status = link.LinkConnectionStatus; 
       int timeout = 0; 
       while (status != APNLink.ConnectionStatus.Connected) 
       { 
        Thread.Sleep(500); 
        status = link.LinkConnectionStatus; 
        if (status == APNLink.ConnectionStatus.Connected) 
        { 
         break; 
        }       
        if (timeout++ > 16) 
        { 
         var msg1 = Request.CreateResponse(HttpStatusCode.RequestTimeout); 
         return msg1; 
        } 
       } 
       link.RelayCommand(APNLink.RelayNumber.Relay1, APNLink.RelayCommand.OFF, test); 
       BlockForResponse(); 
       var msg = Request.CreateResponse(HttpStatusCode.OK); 
       return msg; 
      } 
      else 
      { 
       var msg2 = Request.CreateResponse(HttpStatusCode.BadRequest); 
       return msg2; 
      } 
     } 

    } 

    bool flag = false; 

    public void test(bool var) 
    { 
    flag = true; 
    } 

    private static bool BlockForResponse() 
    { 
     int count = 0; 
     while (!flag) 
     { 
      Thread.Sleep(500); 
      if (count > 10) 
      { 
       //timeout 
       return false; 
      } 
     } 
     return true; 
    } 

теперь вещь, я должен блокировать при ожидании DLL, соединения для подключения, только тогда я могу выполнить команду. как только я выполнил команду. Затем я должен снова заблокировать ответ.

Другой аспект: могу ли я фактически заблокировать поток asp.net? Разумеется, каждый запрос не обрабатывается в собственной ветке?

Есть ли способ сделать этот код более аккуратным и, самое главное, более эффективным?

+1

Вопросы по улучшению кода должна быть на http://codereview.stackexchange.com –

+0

Предоставляет ли ваш апи любой асинхронной версии 'RelayCommand', т.е. 'BeginRelayCommand'? –

+0

Возвращаемая подпись должна быть изменена на 'Task '. http://stackoverflow.com/questions/14068515/using-async-await-and-returning-taskhttpresponsemessage-from-asp-net-web-api-m – rwong

ответ

3

Отвечая на вопрос:

В вызове службы Web API, нужно вызвать функцию в библиотеке DLL, которая выполняет асинхронно, а затем дает ответ в обратном вызове функции.

IMO, лучший способ сделать это - сделать ваш метод контроллера асинхронным и использовать TaskCompletionSource для переноса обратного вызова вашей DLL. Некоторые хорошие дополнительные данные:

Код может выглядеть примерно так:

[HttpGet] 
public async Task<HttpResponseMessage> Off(string id) 
{ 
    APNLink.Link link = LinkProvider.getDeviceLink(id, User.Identity.Name); 

    if (link.LinkConnectionStatus == APNLink.ConnectionStatus.Connected) 
    { 
     var tcs = new TaskCompletionSource<object>(); 

     CallbackType test = delegate {   
      tcs.SetResult(null); 
     }; 

     link.RelayCommand(
      APNLink.RelayNumber.Relay1, 
      APNLink.RelayCommand.OFF, 
      test); 

     // BlockForResponse(); 
     await tcs.Task; // non-blocking 

     var msg = Request.CreateResponse(HttpStatusCode.OK); 
     return msg; 
    } 

    // ... 
} 
+1

Занято Чтение ссылок, которые вы предоставили. Они великолепны. Именно то, что я ищу, так как мои вызовы в dll могут занять до 10 секунд. Поэтому я определенно считаю, что мне нужно использовать асинхронные методы. – Zapnologica

+0

@ Zapnologica, обязательно прочитайте [некоторые другие ссылки] (http://stackoverflow.com/tags/async-await/info), особенно [о том, как работает AspNetSynchronizationContext] (http://msdn.microsoft.com). /en-us/magazine/gg598924.aspx). – Noseratio

Смежные вопросы