Ran*_*iff 1 c# asynchronous asp.net-web-api
我在这个主题上找到了很多,但似乎没有一个例子/答案能解决我们的问题。我们不断收到警告说下面的方法(和其他类似的方法)缺少等待,但是当我们尝试添加等待时,我们得到“无法等待”(无论我们尝试添加等待的地方)。我们做错了什么?
protected async Task<T> PerformGet<T>(string requestUri, bool appendHeader)
{
try
{
_webApiClient = new HttpClient { BaseAddress = _baseAddress };
if (appendHeader) AppendDefaultHeaders();
var webApiResponse = Task.Run(() => _webApiClient.GetAsync(requestUri)).Result;
var responseContent = webApiResponse.Content.ReadAsStringAsync().Result;
return JsonConvert.DeserializeObject<T>(responseContent);
}
catch (Exception ex) {
throw ex;
}
}
Run Code Online (Sandbox Code Playgroud)
非常感谢任何帮助!
async 是一个关键字,用于将方法标记为编译器完全重写以支持异步/等待模式的候选方法。
发生的情况是该方法在您在await内部使用关键字的每个点都被拆分。如果您将方法标记为async但不使用await它,则会抱怨您将其标记为不必要,或者您忘记使用await. 所以这就是你得到编译器错误的原因。
现在,下一步是添加await到您的方法中,但这意味着稍微更改它:
.Result在任务上使用容易出现死锁,这就是await派上用场的地方所以让我们重写你的方法。首先,我们去掉调用Task.Result并替换为await:
protected async Task<T> PerformGet<T>(string requestUri, bool appendHeader)
{
try
{
_webApiClient = new HttpClient { BaseAddress = _baseAddress };
if (appendHeader) AppendDefaultHeaders();
var webApiResponse = await Task.Run(() => _webApiClient.GetAsync(requestUri));
var responseContent = await webApiResponse.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(responseContent);
}
catch (Exception ex) {
throw ex;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我们摆脱了不必要的 task-in-task:
protected async Task<T> PerformGet<T>(string requestUri, bool appendHeader)
{
try
{
_webApiClient = new HttpClient { BaseAddress = _baseAddress };
if (appendHeader) AppendDefaultHeaders();
var webApiResponse = await _webApiClient.GetAsync(requestUri);
var responseContent = await webApiResponse.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(responseContent);
}
catch (Exception ex) {
throw ex;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我们去掉不必要的 try/catch:
protected async Task<T> PerformGet<T>(string requestUri, bool appendHeader)
{
_webApiClient = new HttpClient { BaseAddress = _baseAddress };
if (appendHeader) AppendDefaultHeaders();
var webApiResponse = await _webApiClient.GetAsync(requestUri);
var responseContent = await webApiResponse.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(responseContent);
}
Run Code Online (Sandbox Code Playgroud)
然后我们将HttpClient对象放入using语句中:
protected async Task<T> PerformGet<T>(string requestUri, bool appendHeader)
{
using (var client = new HttpClient { BaseAddress = _baseAddress })
{
if (appendHeader) AppendDefaultHeaders(client);
var response = await client.GetAsync(requestUri);
var responseContent = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(responseContent);
}
}
Run Code Online (Sandbox Code Playgroud)
这将删除字段,这在进行异步工作时通常是一个坏主意,并使其成为此方法的本地概念。这还需要更改AppendDefaultHeaders方法以接受它应该将标头添加为参数的客户端。