http请求在嵌套的异步任务<T>方法中不起作用
http request not working in nested async Task<T> methods
我是第一次使用异步任务,我遇到了一个我似乎无法解决的问题。
我有一个使用 Http 请求调用 API 的方法。
internal static async Task<HttpResponse> CallAPI(string objectname, string parameters, HttpMethod method)
{
HttpResponse r = new HttpResponse();
using (r.HttpClient = new HttpClient())
{
r.HttpClient.BaseAddress = new Uri("https://" + Properties.Settings.Default.APIURL + "/");
r.HttpClient.DefaultRequestHeaders.Clear();
r.HttpClient.DefaultRequestHeaders.Add("Accept", "application/vnd+json;version=1");
r.HttpClient.DefaultRequestHeaders.Add("Host", Properties.Settings.Default.APIURL);
r.HttpClient.DefaultRequestHeaders.Add("Expect", "100-continue");
r.HttpClient.DefaultRequestHeaders.Add("Connection", "Close");
switch (method)
{
case HttpMethod.DELETE:
using (r.ResponseMessage = await r.HttpClient.DeleteAsync("api/" + objectname.ToString() + "/" + parameters))
{
var stopwatch = Stopwatch.StartNew();
r.responseTime = Convert.ToInt32(stopwatch.ElapsedMilliseconds);
r.ResponseData = await r.ResponseMessage.Content.ReadAsStringAsync();
return r;
}
case HttpMethod.GET:
using (r.ResponseMessage = await r.HttpClient.GetAsync("api/" + objectname.ToString() + parameters))
{
var stopwatch = Stopwatch.StartNew();
r.responseTime = Convert.ToInt32(stopwatch.ElapsedMilliseconds);
r.ResponseData = await r.ResponseMessage.Content.ReadAsStringAsync();
return r;
}
default: throw new Exception("No HTTP Method Found");
}
}
我从按钮单击事件中调用 class 中的 delete() 方法:
protected void btnDelete_Click(object sender, EventArgs e)
{
Activity a = new Activity();
a.Id = Convert.ToInt32(txtObjectId.text);
//a.Delete(); //void method
bool done = a.Delete().Result; //Task<bool> method
}
如果我将 delete() 方法设为无效,它会正常工作并且 returns http 响应
public async virtual void Delete()
{
HttpResponse r = new HttpResponse();
r = await CallAPI(_Objectname.ToString(), _Id.ToString(), HttpMethod.DELETE);
}
但是如果我尝试将 Delete() 设为任务,
public async virtual Task<bool> Delete()
{
try
{
HttpResponse r = new HttpResponse();
r = await CallAPI(_Objectname.ToString(), _Id.ToString(), HttpMethod.DELETE);
return true;
}
catch
{
return false;
}
}
它尝试执行 httpclient.deleteasync 方法,但应用程序什么也没做。我没有得到异常,它没有冻结,它似乎不再做任何事情了。
我不知道是什么导致了这种行为,但我对异步编程还很陌生,所以我可能正在做一些我不应该做的事情:-)
如果您在使用 async/await you will deadlock your program 的代码上执行 .Result
或 .Wait()
,您必须使您的事件处理程序 async void
,这是唯一的允许您使用 async void
.
的地方
protected async void btnDelete_Click(object sender, EventArgs e)
{
Activity a = new Activity();
a.Id = Convert.ToInt32(txtObjectId.text);
//await a.Delete(); //Task method
bool done = await a.Delete(); //Task<bool> method
}
如果你最终使用的版本不是 return Task<bool>
,Delete()
函数看起来像
public async virtual Task Delete()
{
HttpResponse r = new HttpResponse();
r = await CallAPI(_Objectname.ToString(), _Id.ToString(), HttpMethod.DELETE);
}
您不需要 return
声明。
此外,如果您不需要访问 UI,请将 .ConfigurateAwait(false)
添加到每个 await 调用,以使其不会强制 UI 线程继续。
public async virtual Task Delete()
{
HttpResponse r = new HttpResponse();
r = await CallAPI(_Objectname.ToString(), _Id.ToString(), HttpMethod.DELETE).ConfigureAwait(false);
}
你也可以对 CallAPI
做同样的事情,让它 运行 变得更好。
我是第一次使用异步任务,我遇到了一个我似乎无法解决的问题。
我有一个使用 Http 请求调用 API 的方法。
internal static async Task<HttpResponse> CallAPI(string objectname, string parameters, HttpMethod method)
{
HttpResponse r = new HttpResponse();
using (r.HttpClient = new HttpClient())
{
r.HttpClient.BaseAddress = new Uri("https://" + Properties.Settings.Default.APIURL + "/");
r.HttpClient.DefaultRequestHeaders.Clear();
r.HttpClient.DefaultRequestHeaders.Add("Accept", "application/vnd+json;version=1");
r.HttpClient.DefaultRequestHeaders.Add("Host", Properties.Settings.Default.APIURL);
r.HttpClient.DefaultRequestHeaders.Add("Expect", "100-continue");
r.HttpClient.DefaultRequestHeaders.Add("Connection", "Close");
switch (method)
{
case HttpMethod.DELETE:
using (r.ResponseMessage = await r.HttpClient.DeleteAsync("api/" + objectname.ToString() + "/" + parameters))
{
var stopwatch = Stopwatch.StartNew();
r.responseTime = Convert.ToInt32(stopwatch.ElapsedMilliseconds);
r.ResponseData = await r.ResponseMessage.Content.ReadAsStringAsync();
return r;
}
case HttpMethod.GET:
using (r.ResponseMessage = await r.HttpClient.GetAsync("api/" + objectname.ToString() + parameters))
{
var stopwatch = Stopwatch.StartNew();
r.responseTime = Convert.ToInt32(stopwatch.ElapsedMilliseconds);
r.ResponseData = await r.ResponseMessage.Content.ReadAsStringAsync();
return r;
}
default: throw new Exception("No HTTP Method Found");
}
}
我从按钮单击事件中调用 class 中的 delete() 方法:
protected void btnDelete_Click(object sender, EventArgs e)
{
Activity a = new Activity();
a.Id = Convert.ToInt32(txtObjectId.text);
//a.Delete(); //void method
bool done = a.Delete().Result; //Task<bool> method
}
如果我将 delete() 方法设为无效,它会正常工作并且 returns http 响应
public async virtual void Delete()
{
HttpResponse r = new HttpResponse();
r = await CallAPI(_Objectname.ToString(), _Id.ToString(), HttpMethod.DELETE);
}
但是如果我尝试将 Delete() 设为任务,
public async virtual Task<bool> Delete()
{
try
{
HttpResponse r = new HttpResponse();
r = await CallAPI(_Objectname.ToString(), _Id.ToString(), HttpMethod.DELETE);
return true;
}
catch
{
return false;
}
}
它尝试执行 httpclient.deleteasync 方法,但应用程序什么也没做。我没有得到异常,它没有冻结,它似乎不再做任何事情了。
我不知道是什么导致了这种行为,但我对异步编程还很陌生,所以我可能正在做一些我不应该做的事情:-)
如果您在使用 async/await you will deadlock your program 的代码上执行 .Result
或 .Wait()
,您必须使您的事件处理程序 async void
,这是唯一的允许您使用 async void
.
protected async void btnDelete_Click(object sender, EventArgs e)
{
Activity a = new Activity();
a.Id = Convert.ToInt32(txtObjectId.text);
//await a.Delete(); //Task method
bool done = await a.Delete(); //Task<bool> method
}
如果你最终使用的版本不是 return Task<bool>
,Delete()
函数看起来像
public async virtual Task Delete()
{
HttpResponse r = new HttpResponse();
r = await CallAPI(_Objectname.ToString(), _Id.ToString(), HttpMethod.DELETE);
}
您不需要 return
声明。
此外,如果您不需要访问 UI,请将 .ConfigurateAwait(false)
添加到每个 await 调用,以使其不会强制 UI 线程继续。
public async virtual Task Delete()
{
HttpResponse r = new HttpResponse();
r = await CallAPI(_Objectname.ToString(), _Id.ToString(), HttpMethod.DELETE).ConfigureAwait(false);
}
你也可以对 CallAPI
做同样的事情,让它 运行 变得更好。