HttpClient c# - 在SendASync中取消了一项任务

时间:2017-10-11 07:50:38

标签: c# wpf visual-studio httpclient

即使我增加超时,我也会得到TaskCanceledException。令人惊讶的是它甚至不会一直发生,异常仅在某个时间发生,我无法找到模式来重现错误。我添加了用于进行网络呼叫的异常跟踪和代码。

Exception Trace Image

public static void getResponseFromUrlAsync<T>(T payload, string url,
     Action<string> onSuccess, Action<string> onFailure)
{
    string contentType = "application/json";
    httpClient = new HttpClient();
    httpClient.Timeout = TimeSpan.FromMinutes(30);
    HttpRequestMessage requestMsg = new HttpRequestMessage();
    requestMsg.RequestUri = new Uri(NetworkCallUrls.baseUri + url);
    Utils.debugLog("Url", NetworkCallUrls.baseUri + url);

    // try
    //{
    string auth = "Bearer " + Objects.GlobalVars.GetValue<string>("access_token"); // //"x1VwaR1otS66ZCTlgtv3X9aaSNpDOn"; //
    httpClient.DefaultRequestHeaders.Add("Authorization", auth);
    requestMsg.Method = HttpMethod.Post;

    requestMsg.Content = new StringContent(
                   Utils.stringifyData(payload),
                   Encoding.UTF8,
                   contentType);

    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));//ACCEPT header

    makeNetworkCallCheckResponseStatusAndExecuteCorrospondingAction(requestMsg, onSuccess, onFailure, progressBarStatus);
}

internal static void disposeConnection(HttpClient httpClient)
{
    httpClient.Dispose();
    httpClient = null;
}

private static async void makeNetworkCallCheckResponseStatusAndExecuteCorrospondingAction(
    HttpRequestMessage requestMsg, Action<string> onSuccess,
    Action<string> onFailure, Action<bool> progressBarStatus)
{
    Utils.debugLog("IN MAKE NETWORK CALL 1");
    HttpResponseMessage response = await httpClient.SendAsync(requestMsg);
    Utils.debugLog("IN MAKE NETWORK CALL 2");
    ResponseStatus responseStatus = checkResponseStatusAndExecuteActionAccordinglyAsync(response);
    Utils.debugLog("IN MAKE NETWORK CALL 3");
    if (responseStatus.isSuccess)
    {
        Utils.debugLog("IN MAKE NETWORK CALL 4");
        string responseString = await response.Content.ReadAsStringAsync();
        Utils.debugLog("IN MAKE NETWORK CALL 5");
        onSuccess(responseString);
        Utils.debugLog("IN MAKE NETWORK CALL 6");
    }
    else
    {
        Utils.debugLog("IN MAKE NETWORK CALL 7");
        onFailure(responseStatus.failureResponse);
        Utils.debugLog("IN MAKE NETWORK CALL 8");
    }
    Utils.debugLog("IN MAKE NETWORK CALL 9");
    disposeConnection(httpClient);
    Utils.debugLog("IN MAKE NETWORK CALL 10");
}

我使用上面的代码进行API调用,我在HttpResponseMessage response = await httpClient.SendAsync(requestMsg);行中得到TaskCanceledException。

可以帮助我解决这个问题。我在互联网上搜索并增加超时但没有用。

2 个答案:

答案 0 :(得分:2)

我希望有些评论可以帮助您解决问题:

    如果您没有任何要返回的内容,则
  1. async方法应返回Task,而不是void。您不必实际返回Task对象,编译器将处理此问题。唯一的例外是WinForms和WebForms事件处理程序。
  2. 您的getResponseFromUrlAsync方法不是异步,但它应该是。您应该添加async修饰符,然后返回Task。然后,await makeNetworkCallCheckResponseStatusAndExecuteCorrospondingAction(...)。这可能是您的问题的根源 - 在返回之前,您没有等待异步操作完成。
  3. 总的来说,似乎你的httpClient变量是全局定义的。您可以轻松地遇到NullReferenceException,因为即使不先调用makeNetworkCallCheckResponseStatusAndExecuteCorrospondingAction也可以调用getResponseFromUrlAsyncdisposeConnection也可以调用httpClient。如果您的类始终使用DatetimeIndex,请在构造函数或声明中初始化它。如果不是,请检查方法开头是否为空。

答案 1 :(得分:1)

您应该等待makeNetworkCallCheckResponseStatusAndExecuteCorrospondingAction方法和getResponseFromUrlAsync方法。这意味着您需要将返回类型从void更改为Task

public static async Task getResponseFromUrlAsync<T>(T payload, string url, Action<string> onSuccess, Action<string> onFailure)
{
    string contentType = "application/json";
    httpClient = new HttpClient();
    httpClient.Timeout = TimeSpan.FromMinutes(30);
    HttpRequestMessage requestMsg = new HttpRequestMessage();
    requestMsg.RequestUri = new Uri(NetworkCallUrls.baseUri + url);
    Utils.debugLog("Url", NetworkCallUrls.baseUri + url);


    string auth = "Bearer " + Objects.GlobalVars.GetValue<string>("access_token"); // //"x1VwaR1otS66ZCTlgtv3X9aaSNpDOn"; //
    httpClient.DefaultRequestHeaders.Add("Authorization", auth);
    requestMsg.Method = HttpMethod.Post;

    requestMsg.Content = new StringContent(
                   Utils.stringifyData(payload),
                   Encoding.UTF8,
                   contentType);

    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));//ACCEPT header

    await makeNetworkCallCheckResponseStatusAndExecuteCorrospondingAction(requestMsg, onSuccess, onFailure, progressBarStatus)
        .ConfigureAwait(false);
}

internal static void disposeConnection(HttpClient httpClient)
{
    httpClient.Dispose();
    httpClient = null;
}

private static async Task makeNetworkCallCheckResponseStatusAndExecuteCorrospondingAction(
    HttpRequestMessage requestMsg, Action<string> onSuccess,
    Action<string> onFailure, Action<bool> progressBarStatus)
{
    Utils.debugLog("IN MAKE NETWORK CALL 1");
    HttpResponseMessage response = await httpClient.SendAsync(requestMsg).ConfigureAwait(false);
    Utils.debugLog("IN MAKE NETWORK CALL 2");
    ResponseStatus responseStatus = checkResponseStatusAndExecuteActionAccordinglyAsync(response);
    Utils.debugLog("IN MAKE NETWORK CALL 3");
    if (responseStatus.isSuccess)
    {
        Utils.debugLog("IN MAKE NETWORK CALL 4");
        string responseString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
        Utils.debugLog("IN MAKE NETWORK CALL 5");
        onSuccess(responseString);
        Utils.debugLog("IN MAKE NETWORK CALL 6");
    }
    else
    {
        Utils.debugLog("IN MAKE NETWORK CALL 7");
        onFailure(responseStatus.failureResponse);
        Utils.debugLog("IN MAKE NETWORK CALL 8");
    }
    Utils.debugLog("IN MAKE NETWORK CALL 9");
    disposeConnection(httpClient);
    Utils.debugLog("IN MAKE NETWORK CALL 10");
}

...和await调用它时的方法:

await getResponseFromUrlAsync<..>(...);