我可以摆脱这个可怕的阻止代码吗?

时间:2014-03-12 05:45:36

标签: c# multithreading asynchronous task-parallel-library blocking

我需要一些帮助,在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 个答案:

答案 0 :(得分: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;
    }

    // ...
}