1

我需要一些帮助,在一个web api服务调用中,我需要调用一个dll中异步执行的函数,然后在回调函数中给出响应。现在通常这会很好,但现在使用web api的想法是执行命令并返回响应。我可以摆脱这个可怕的封锁代码吗?

下面是我当前的代码,它的工作原理,但我认为它的可怕的代码,你不想做的一切。特别是在Web服务器上,当这个代码要运行每个请求时。

[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

请问您的API提供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