【问题标题】:PostAsJsonAsync not sending request when awaitedPostAsJsonAsync 在等待时不发送请求
【发布时间】:2017-01-07 02:39:11
【问题描述】:

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

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");
    }

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

【问题讨论】:

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


    【解决方案1】:

    你不是在等待Process() 完成执行——你只是触发异步操作,忘记它并返回:

    Process();
    

    您应该等待任务完成。例如

    Process().Wait();
    

    应用程序在其主线程终止时终止。不管你有多少后台线程。当主线程终止时,它们都会被自动杀死。因此,您有两种选择可以让您的应用程序在后台线程工作时保持活动状态:

    1. 停止主线程并等待后台线程。
    2. 在后台线程执行时在主线程上做一些工作。

    让我们考虑第一个选项。如果有很多后台线程,那么您将拥有多线程异步应用程序。主线程被阻塞,但有许多其他线程并行执行它们的工作。但是如果你有一个后台线程呢?主要线程正在等待它,并且您有多线程同步应用程序。那是你的情况。

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

    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 来提供取消它们的选项。

    【讨论】:

    • 但如果它是“火灾并忘记”,那么“火灾”不会影响我的服务。
    • @fz8975 因为它也是并返回 - 应用程序在请求发送之前终止。似乎简单的返回比创建 http 客户端、生成请求并通过网络发送更快
    • @fz8975 - 正如我认为 Stephen Cleary 曾经写过的那样,您通常应该将“fire and forget”视为“fire and crash”(我可能会解释一下)。
    • 添加 Wait() 后,它的行为是同步的。我的服务是增量插入记录。我该怎么办?
    • @fz8975 我已经更新了答案,提供了更多详细信息和解释。但是您的代码不会增量插入记录。如果您有其他代码,请考虑提出有关该代码的新问题
    猜你喜欢
    • 1970-01-01
    • 2011-01-12
    • 2015-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-30
    • 1970-01-01
    • 2013-11-18
    相关资源
    最近更新 更多