即使处理了发送的数据,HttpClient.SendAsync也会保持不变

时间:2016-02-12 14:25:43

标签: c# asp.net-mvc asynchronous async-await .net-4.6

我不得不重写从ASP.Net CoreASP.Net 4.6.1的应用程序,在应用程序的核心版本中,我将Json数据发送到BugZilla进行处理,它运行正常。它发送数据并相当快地获得响应。 4.6.1版本的应用程序中的相同代码位于send命令上并挂起。我可以进入BugZilla并看到它获取数据并生成错误,但即使在15分钟后应用程序也无法进展。我是Task的新手,并通过Json发送数据,所以我不知道为什么我遇到这个问题。没有错误返回,在调试模式下,我可以逐步完成所有操作,并知道它正在SendAsync行处理并等待。我在4.6.1中打破这个错误做错了什么?

private static async Task<int> LogToBugZilla(string Component, Exception ex)
{
    var ErrorSummary = "Auto Error Logging: " + ex.Message + " " + ex.InnerException.Message;

    var BugData = new Dictionary<string, string>
    {
        { "Bugzilla_api_key", ConfigurationManager.AppSettings["BugZillaAPIKey"] },
        { "product", "Job Site" },
        { "component", Component },
        { "version", ConfigurationManager.AppSettings["AppVersion"] },
        { "summary", ErrorSummary },
        { "op_sys", "All" },
        { "platform", "Other" },
        { "description", ex.StackTrace + ex.InnerException.StackTrace }
    };

    string Json = JsonConvert.SerializeObject(BugData, Formatting.None);
    var Client = new HttpClient();
    var Request = new HttpRequestMessage(HttpMethod.Post, "http://bugzilla/rest/bug");
    Request.Content = new StringContent(Json, Encoding.UTF8, "application/json");
    Request.Headers.Add("Accept", "application/json");
    var Response = await Client.SendAsync(Request);
    var JsonResults = await Response.Content.ReadAsStringAsync();

    if (Response.StatusCode == HttpStatusCode.OK)
    {
        var Results = JsonConvert.DeserializeObject<Dictionary<string, int>>(JsonResults);
        return Results["id"];
    }
    else
    {
        return -1;
    }
}

编辑:

public static string ProcessError(Exception ex, string OriginatingController)
{
    var Component = GetComponent(OriginatingController);
    string UserErrorMessage = "";

    switch (ex.GetType().ToString())
    {
        case "System.Data.DataException":
            LogToITSupport("Database Connection");
            UserErrorMessage = @"An error has accrued connecting to the database. <a href=""mailto:"">IT Support</a> has been notified  of this error. Please try your request again later, thank you.";
            break;

        default:
            var BugID = LogToBugZilla(Component, ex).Result;
            UserErrorMessage = @"An error has accrued processing your request and a log of this error has been made on the <a href=""http://bugzilla/show_bug.cgi?id=" + BugID + "\">Internal Tools BugZilla system</a> with an ID of " + BugID + ". Please try your request again later, thank you.";
            break;
    }

    return UserErrorMessage;
}

要重申,应用程序会挂起代码var Response = await Client.SendAsync(Request);

编辑2:

Contrller代码:

public ActionResult About()
{
    try
    {
        using (var db = new JobSightDbContext())
        {
            var model = db.ReleaseVersions
                            .OrderByDescending(rv => rv.DateReleased)
                            .Select(rv => new ReleaseNotesVM()
                            {
                                ID = rv.ID,
                                CurrentVersion = string.Concat(rv.Major, ".", rv.Minor, ".", rv.Patch),
                                CurrentVersionReleaseDate = rv.DateReleased,
                                ReleaseNotes = rv.ReleaseNotes.Select(rn => rn.Note).ToList()
                            }).First();

            //model.VersionList = db.ReleaseVersions
            //                      .OrderByDescending(rv => rv.DateReleased)
            //                      .Select(rv => new SelectListItem()
            //                      {
            //                          Value = rv.ID.ToString(),
            //                          Text = string.Concat(rv.Major, '.', rv.Minor, '.', rv.Patch)
            //                      }).ToList();

            return View(model);
        }
    }
    catch (System.Data.DataException ex)
    {
        ViewBag.ErrorMessage = EHALM.ProcessError(ex, RouteData.Values["controller"].ToString());
        return View("Dashboard");
    }
}

2 个答案:

答案 0 :(得分:4)

我会在这里跛行,并说你在你的调用堆栈中使用LogToBugZilla更高的位置:

public void DoStuff()
{
    var result = LogToBugZilla("Component", exception).Result;
}

这实际上使代码陷入僵局,这就是you shouldn't block on async code的原因。您需要将代码&#34; async一直保持为#34;,直到调用堆栈的顶部。这意味着将DoStuff转为DoStuffAsync并将其称为:

public async Task DoStuffAsync()
{
    var result = await LogToBugZillaAsync("Component", exception);
    // Do stuff with result
}

注意我添加了&#34; async&#34;根据推荐的编码约定,后缀为LogToBugZilla

修改

鉴于您提供了调用方法,它应如下所示:

public static async Task<string> ProcessErrorAsync(
            Exception ex, string OriginatingController)
{
    var Component = GetComponent(OriginatingController);
    string UserErrorMessage = "";

    switch (ex.GetType().ToString())
    {
        case "System.Data.DataException":
            LogToITSupport("Database Connection");
            UserErrorMessage = @"An error has accrued connecting to the 
            database. <a href=""mailto:"">IT Support</a> has been notified
            of this error. Please try your request again later, thank you.";
            break;

        default:
            var bugId = await LogToBugZillaAsync(Component, ex);
            UserErrorMessage = @"An error has accrued processing your request 
            and a log of this error has been made 
            on the <a href=""http://bugzilla/show_bug.cgi?id=" + BugID +
            "\">Internal Tools BugZilla system</a> 
            with an ID of " + bugId + ". Please try your request again later, thank you.";
            break;
    }
    return UserErrorMessage;
}

现在请记住,这需要一路向上。这意味着调用ProcessErrorAsync的每个方法本身都应该async并返回TaskTask<T>

答案 1 :(得分:1)

这是我用来发送HTTP请求的一些通用代码。工作正常只有差异是我使用.Net 4.5。应该不是4.6的问题

private async Task<HttpUtilResponse> DoRequest(List<RequestResponseHeader> headers, HttpMethod method, string url, string requestData) {
     HttpUtilResponse response = new HttpUtilResponse();
     string responseData = string.Empty;
     using (System.Net.Http.HttpClient client = new System.Net.Http.HttpClient()) {          
        using (HttpRequestMessage request = new HttpRequestMessage(method, url)) {
           if (headers != null) {
              headers.ForEach(h => request.Headers.Add(h.Name, h.Value));
           }               
           if (!string.IsNullOrEmpty(requestData)) {
              if (AppConfig.LogRequestContent) {
                 LOG.Debug(requestData);
              }
              request.Content = new StringContent(requestData, Encoding.UTF8, JSON_CONTENT);                  
           }
           using (HttpResponseMessage msg = await client.SendAsync(request, CancelToken.Token)) {
              response.StatusCode = msg.StatusCode;
              response.ReasonPhrase = msg.ReasonPhrase;
              using (HttpContent content = msg.Content) {
                 response.ResponseText = await content.ReadAsStringAsync();
              }
           }
        }
     }
     return response;
  }