等待时,PostAsJsonAsync不发送请求

时间:2017-01-07 02:39:12

标签: c# asp.net-web-api async-await

我有一个ServiceInvoker,它调用Web API(POST端点)

public  async Task<HttpResponseMessage> InvokeService(string url, string action)
{
    string requestUri = @"api/MyController/" + action;
    HttpResponseMessage response;
    HttpClientHandler handler = new HttpClientHandler()
    {
        UseDefaultCredentials = true
    };
    using (var client = new HttpClient(handler))
    {
        client.BaseAddress = new Uri(url);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        response =await client.PostAsJsonAsync(requestUri, myObj);

    }
    return response;
}

当我调试时,PostAsJsonAsync执行后,控件转到main()。也没有调试我无法点击该服务。它在我这样做时起作用

response =client.PostAsJsonAsync(requestUri, myObj).Result;

但它是同步的。

此方法从main()

调用
    void main()
    {
        Start()
    }
    public void Start()
    {
        Process();
    }
    public async Task Process()
    {
        HttpResponseMessage servResponse;
        servResponse=await InvokeService("http://myServiceUrl","myAction");
    }

我的要求是从不同的应用程序中对服务进行大量调用。我想调用异步来提高性能。

1 个答案:

答案 0 :(得分:2)

您没有等待Process()完全执行 - 您只需触发异步操作,忘记它并返回:

Process();

您应该等待任务完成。 E.g。

Process().Wait();

应用程序在主线程终止时终止。你有多少背景线程并不重要。当主线程终止时,它们都将被自动杀死。因此,在后台线程正在执行其工作时,您有两个选项可以使应用程序保持活动状态:

  1. 停止主线程并等待后台线程。
  2. 在后台线程执行时,在主线程上做一些工作。
  3. 让我们考虑第一个选择。如果有许多后台线程,那么您将拥有多线程异步应用程序。主线程被阻止,但还有许多其他线程并行执行。但是如果你有单一的后台线程怎么办?主要是等待它,你有多线程同步应用程序。这是你的理由。

    现在第二个选项。在后台线程执行时在主线程上执行某些操作 - 是使用异步操作的重点。 但你的应用程序与主线程无关。当然你可以模拟一些工作。即使有像

    这样的东西
    Process(); // fire and forget
    while (true); // make your main thread busy
    

    这将使您的应用程序成为多线程和异步的。但主线程将忙于消耗CPU资源。没有其他的。如果你在主线上有一些真实的东西:

    var task = Process();
    DoSomeRealJobHere();
    task.Wait(); // still you need to wait for background task
    

    或者,如果您希望应用程序更具互动性

     var task = Process();
     do
     {
         DoSomethingHere(); // e.g display current weather info
     } while (!task.IsCompleted);
    

    注意:如果您使用的是异步操作,请考虑通过传递CancelationToken来提供取消它们的选项。