我想在我的程序,实现如下调用堆栈/工作流程:死锁
- 讯()
- 授权()
- httpPost()
我的想法是,httpPost()
将是异步的,而另外两种方法仍然是非异步的。但是,由于某种原因,除非我做了2 + 3,否则它不适用于我。异步。也许我仍然有一些误解。
据我的理解,我可以a)在调用异步方法时使用await
关键字(这将挂起方法并在异步方法完成后继续)或者b)省略关键字,而是调用Task。异步方法的结果返回值,该值将阻塞直到结果可用。
让我告诉你的工作示例:
private int dispatch(string options)
{
int res = authorize(options).Result;
return res;
}
static async private Task<int> authorize(string options)
{
string values= getValuesFromOptions(options);
KeyValuePair<int, string> response = await httpPost(url, values);
return 0;
}
public static async Task<KeyValuePair<int, string>> httpPost(string url, List<KeyValuePair<string, string>> parameters)
{
var httpClient = new HttpClient(new HttpClientHandler());
HttpResponseMessage response = await httpClient.PostAsync(url, new FormUrlEncodedContent(parameters));
int code = (int)response.StatusCode;
response.EnsureSuccessStatusCode();
string responseString = await response.Content.ReadAsStringAsync();
return new KeyValuePair<int, string>(code, responseString);
}
让我告诉你的非木材加工例如:
private int dispatch(string options)
{
int res = authorize(options).Result;
return res;
}
static private int authorize(string options)
{
string values= getValuesFromOptions(options);
Task<KeyValuePair<int, string>> response = httpPost(url, values);
doSomethingWith(response.Result); // execution will hang here forever
return 0;
}
public static async Task<KeyValuePair<int, string>> httpPost(string url, List<KeyValuePair<string, string>> parameters)
{
var httpClient = new HttpClient(new HttpClientHandler());
HttpResponseMessage response = await httpClient.PostAsync(url, new FormUrlEncodedContent(parameters));
int code = (int)response.StatusCode;
response.EnsureSuccessStatusCode();
string responseString = await response.Content.ReadAsStringAsync();
return new KeyValuePair<int, string>(code, responseString);
}
我也试图让所有3种方法非异步,并替换httpPost
中的await
与.Result
S,但随后它会永远在该行挂HttpResponseMessage response = httpClient.PostAsync(url, new FormUrlEncodedContent(parameters)).Result;
可能有人开导我,并说明我的错误是什么?
若要测试这是否正确的解释,采取非工作代码并将每个“await X”更改为“await X.ConfigureAwait(false)”。如果解释是正确的,它现在应该工作。 另一个注意事项:如果你在ASP.Net或UI应用程序中运行,你有一个SynchronizationContext。如果是这样,请比较在独立控制台项目中运行相同的代码。 – danarmak
@servy:然而,我没有得到的是我的工作示例和非工作示例之间的实际区别。我明白你说'await'安排了一个延续,'.Result'只是普通块(是这样吗?),但这不会意味着我需要一个无尽的异步等待链,因为没有'await'我会阻止/死锁我的线程? 我的意思是第一个例子在'int res = authorize(options).Result;'中不*拦截,但第二个例子在'doSomethingWith(response.Result)中拦截;为什么? – user826955