HttpClient c# - SendASync中取消任务

问题描述:

即使增加超时,我也得到TaskCanceledException。令人惊讶的是,它甚至不会总是发生,异常只发生在某个时间,我无法找到重现错误的模式。我添加了用于进行网络调用的异常跟踪和代码。HttpClient c# - SendASync中取消任务

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。

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

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

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<..>(...); 
+0

我认为对于我来说,问题是在api call_1完成之前,httpClient已更新为新的,因为我正在多次调用一个接一个,没有任何延迟,所以在返回上一个调用之前,我正在拨打另一个电话 – djkp

+0

但是,将根据最佳实践更新代码,谢谢:) – djkp

+0

这就是为什么你应该等待的方法。 – mm8

,我希望能帮助您解决问题的一些意见:

  1. async方法应该返回Task如果你没有返回,不void。你不必实际返回一个Task对象,编译器会处理这个。唯一的例外是WinForms和WebForms事件处理程序。
  2. 您的getResponseFromUrlAsync方法不是异步的,但它应该是。您应该添加一个async修饰符,并返回Task。然后,await makeNetworkCallCheckResponseStatusAndExecuteCorrospondingAction(...)。这可能是问题的根源 - 在返回之前,您并未等待异步操作完成。
  3. 在一般说明中,似乎您的httpClient变量是在全局某个地方定义的。你可以很容易地遇到一个NullReferenceException,因为makeNetworkCallCheckResponseStatusAndExecuteCorrospondingAction甚至可以不用先调用getResponseFromUrlAsyncdisposeConnection也可以调用。如果您的课程始终使用httpClient,请在构造函数或声明中对其进行初始化。如果不是,请在方法开始时检查它是否为空。
+0

对于2日,我在“makeNetworkCallCheckResponseStatusAndExecuteCorrospondingAction”等待所以我想我不需要等待和异步和任务返回'getResponseFromUrlAsync' – djkp

+0

@djkp,你这样做。 'makeNetworkCallCheckResponseStatusAndExecuteCorrospondingAction'是异步的,如果你不等待它,你会在它执行完成之前返回。一旦你开始使用异步,它一直是异步编程的根。 –