C# 从任务中自动删除等待时,SendAsync失败

C# 从任务中自动删除等待时,SendAsync失败,c#,.net,asynchronous,task,httpclient,C#,.net,Asynchronous,Task,Httpclient,我有这个工作登录代码: using (StringContent stringContent = new StringContent(payload, Encoding.UTF8, "application/json")) { HttpRequestMessage request = new HttpRequestMessage() //populate the request request.Content = stringContent;

我有这个工作登录代码:

 using (StringContent stringContent = new StringContent(payload, Encoding.UTF8, "application/json"))
 {
     HttpRequestMessage request = new HttpRequestMessage()
     //populate the request
     request.Content = stringContent;
     try
     {
        using (HttpResponseMessage response = await client
         .SendAsync(request, HttpCompletionOption.ResponseHeadersRead)
         .ConfigureAwait(false))
       {
          response.EnsureSuccessStatusCode();
          _lastRespose = await response.Content.ReadAsStringAsync();
          return _lastRespose;
       }
    }
    catch (Exception)
    { ... }
这很有效。
我想让这段代码异步运行。 因此,我将其更改为获取任务,并使用ContinueWith在呼叫完成时获取回拨

 private async void OnTestLoginCallCompleate(Task<HttpResponseMessage> response)
 {
     if (response.IsFaulted)
     {
         ShowErrorMessage();
         return;
     }
 }

    private void Login(Action<Task<HttpResponseMessage>> loginCallback)
    {
        _username = userNameTB.Text;
        _password = pwTB.Text;
        _url = urlTB.Text;

        if (String.IsNullOrEmpty(_username) ||
            String.IsNullOrEmpty(_password) ||
            String.IsNullOrEmpty(_url))
        {
            MessageBox.Show("All fields must not be empty", "Validation Error", MessageBoxButtons.OK);
        }

        HttpRequestMessage request = new HttpRequestMessage()
        {
            RequestUri = new Uri(_url),
            Method = HttpMethod.Post,
        };

        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        String payload = "{ \"email\": \"" + _username + "\", \"password\": \"" + _password + "\" }";

        using (StringContent stringContent = new StringContent(payload, Encoding.UTF8, "application/json"))
        {
            request.Content = stringContent;
            client.SendAsync(request, HttpCompletionOption.ResponseContentRead).ContinueWith(loginCallback);
        }
    }
private异步void ontestlogincallcomplete(任务响应)
{
if(response.IsFaulted)
{
发送消息();
返回;
}
}
私有无效登录(操作登录回调)
{
_username=userNameTB.Text;
_密码=pwTB.Text;
_url=urlTB.Text;
if(String.IsNullOrEmpty(\u用户名)||
String.IsNullOrEmpty(\u密码)||
String.IsNullOrEmpty(_url))
{
MessageBox.Show(“所有字段不得为空”,“验证错误”,MessageBoxButtons.OK);
}
HttpRequestMessage请求=新建HttpRequestMessage()
{
RequestUri=新的Uri(_url),
方法=HttpMethod.Post,
};
request.Headers.Accept.Add(新的MediaTypeWithQualityHeaderValue(“application/json”);
字符串有效载荷=“{\”电子邮件\“:\”+“用户名+”,“密码\“:\”+“密码+”\”;
使用(StringContent-StringContent=new-StringContent(payload,Encoding.UTF8,“application/json”))
{
request.Content=stringContent;
SendAsync(请求,HttpCompletionOption.ResponseContentRead).ContinueWith(loginCallback);
}
}
回调正常,但我总是得到
响应。IsFaulted
true。
为什么会这样?

通过查看代码,特别是这一部分:

using (StringContent stringContent = new StringContent(payload, Encoding.UTF8, "application/json"))
{
   request.Content = stringContent;
   client.SendAsync(request, HttpCompletionOption.ResponseContentRead).ContinueWith(OnTestLoginCallCompleate);
}
您需要将wait添加到
client.SendAsync
,以便继续正常工作

如果您尝试按如下方式修改代码,它应该可以工作。我已经在我的机器上进行了本地测试(稍加修改,所以运行正常)


正如注释中提到的,问题来自这样一个事实:我使用
包装异步调用。
这将处理HttpResponseMessage,当它到达回调时,它已经被处理。
解决方案是使用
删除
,并在回调中手动处理HttpResponseMessage

private async void OnTestLoginCallCompleate(Task<HttpResponseMessage> response)
 {
     if (response.IsFaulted)
     {
         ShowErrorMessage();
         return;
     }
     HttpResponseMessage result = response.Result;
    ......code....
     result.Dispose();
 }


“我想使此代码异步运行。”->此代码正在异步运行。您没有显示足够的代码来帮助您,但是您应该查看异常属性。您可能应该知道,
await
实际上是
ContinueWith
的一个有条件应用程序,它使用语法糖使其看起来更像传统的顺序代码。不清楚明确引入
ContinueWith
的目的是什么。错误消息是怎么说的?很可能
StringContent
被过早地处理,您会得到一个
ObjectDisposedException
。尝试将异常传递给您的
ShowErrorMessage
方法(
ShowErrorMessage(response.exception.InnerException)
),以便您可以观察/显示错误消息。@TheodorZoulias-是的,这就是问题所在。我没有使用太多的IDsposable对象,因此忽略了显而易见的内容。如果你作为一个单独的答案发布,我会接受。我已经知道了。我正在尝试使代码异步运行而不是同步…@Itamar Kerbel adding await将不会使您的呼叫同步,但它将确保它是异步的,并且主线程未被阻止,并接收更多登录呼叫。如果您跳过等待,那么您将始终得到继续链中的任务出错,因为它取决于上一个任务的结果。我希望它能把事情弄清楚一点,这是不对的。您将获得任务,但它尚未执行。只有在完成第一个任务后,才会执行conitnue with。有关解决方案,请参见上面的注释
private async void OnTestLoginCallCompleate(Task<HttpResponseMessage> response)
 {
     if (response.IsFaulted)
     {
         ShowErrorMessage();
         return;
     }
     HttpResponseMessage result = response.Result;
    ......code....
     result.Dispose();
 }

StringContent stringContent = new StringContent(payload, Encoding.UTF8, "application/json");
request.Content = stringContent;
client.SendAsync(request, HttpCompletionOption.ResponseContentRead).ContinueWith(loginCallback);