我想在程序中实现的是以下callstack / workflow:
我的想法是,httpPost()
将是异步的,而其他2种方法仍然是非同步的。但是,出于某种原因,除非我做了2 + 3,否则它对我不起作用。异步。也许我还有一些误解。
根据我的理解,我可以a)在调用异步方法时使用await
- 关键字(这将挂起方法并在异步方法完成后继续),或b)省略await
-keyword,而是调用async方法的Task.Result返回值,该值将一直阻塞,直到结果可用。
让我告诉你工作的例子:
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种方法都是非同步的,并用await
替换httpPost
中的.Result
,但它会永久地挂在行{{1 }}
有人可以启发我并解释我的错误是什么吗?
答案 0 :(得分:11)
您有一个SynchronizationContext
,并且在await
时正在捕获该上下文,以便继续在该上下文中运行。
您正在启动异步任务,计划在以后的某个时间点在主要上下文中运行。
然后,在异步操作完成之前,您的主上下文中的代码会对异步操作执行阻塞等待。无法安排继续运行,因为上下文正忙于等待继续。经典僵局。
这就是为什么“像你在第一个例子中所做的那样”一直“异步”的原因。
在第二个例子中,有一些黑客可以解决僵局,但它仍然不是你应该做的事情。异步的整个过程就是避免阻塞你的线程。如果你只是对任务进行阻塞等待,那么你就是在打败异步的目的。除非你没有选择,否则要么一切都是异步的,要么都不是异步的。