C# 是否可以停止使用异步并在需要时等待
我正在实现一个使用异步函数的开发人员的代码 例如:C# 是否可以停止使用异步并在需要时等待,c#,multithreading,asynchronous,C#,Multithreading,Asynchronous,我正在实现一个使用异步函数的开发人员的代码 例如: public async Task<string> GetDataAsync(string jsonString = "") { string url = $"{this.url}"; using (HttpClient httpClient = new HttpClient()) { using (StringContent body = new StringContent(jsonStr
public async Task<string> GetDataAsync(string jsonString = "")
{
string url = $"{this.url}";
using (HttpClient httpClient = new HttpClient())
{
using (StringContent body = new StringContent(jsonString, Encoding.UTF8, "application/json"))
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", this.accessToken);
using (HttpResponseMessage response = await httpClient.PostAsync(url, body))
{
switch (response.IsSuccessStatusCode)
{
case true:
return await response.Content.ReadAsStringAsync();
default:
throw new Exception($"Error calling url: {url}. HTTP status: {response.StatusCode}");
}
}
}
}
}
公共异步任务GetDataAsync(字符串jsonString=“”)
{
字符串url=$“{this.url}”;
使用(HttpClient HttpClient=new HttpClient())
{
使用(StringContent body=newstringcontent(jsonString,Encoding.UTF8,“application/json”))
{
httpClient.DefaultRequestHeaders.Authorization=新的AuthenticationHeaderValue(“承载者”,this.accessToken);
使用(HttpResponseMessage响应=等待httpClient.PostAsync(url,正文))
{
开关(响应。IsSuccessStatusCode)
{
大小写正确:
return wait response.Content.ReadAsStringAsync();
违约:
抛出新异常($“调用url时出错:{url}.HTTP状态:{response.StatusCode}”);
}
}
}
}
}
我不需要,也不想,异步调用任何东西。但问题是异步函数一直在我的函数中冒泡,所以我不能停止使用它,因为HttpClient没有一个Post()
函数来代替PostAnync()
,所以我感觉被困在了这个异步框架中
在正常情况下调用异步函数,阻止线程在所有父函数中冒泡,有什么技巧吗
或者说,找到没有异步函数的包的唯一解决方案是什么?简单的回答是-不,没有通用的方法可以将基于任务的异步函数变成同步函数 问题是您不知道它是如何在内部实现的。比如说,异步函数是使用
async
实现的,并且它(部分)在主线程的上下文中运行。然后,如果调用方代码试图通过阻塞调用阻塞主线程,那么async
函数也会被阻塞,这会导致死锁
但是,在您的特定情况下,您可以尝试创建一个新任务,从该任务调用async
函数并获取其结果。有很好的机会,它将工作,但没有保证(如上所述)
代码如下所示:
using (var response = Task.Run(() => httpClient.PostAsync(url, body).Result).Result)
{
...
}
简单的回答是-不,没有通用的方法可以将同步函数转换为基于任务的异步函数 问题是您不知道它是如何在内部实现的。比如说,异步函数是使用
async
实现的,并且它(部分)在主线程的上下文中运行。然后,如果调用方代码试图通过阻塞调用阻塞主线程,那么async
函数也会被阻塞,这会导致死锁
但是,在您的特定情况下,您可以尝试创建一个新任务,从该任务调用async
函数并获取其结果。有很好的机会,它将工作,但没有保证(如上所述)
代码如下所示:
using (var response = Task.Run(() => httpClient.PostAsync(url, body).Result).Result)
{
...
}
Task.Run(GetDataAsync)。结果可能就是您要查找的。它会一直等到异步调用完成。那么,您是否会阻塞异步代码,从而导致死锁?这里真正的问题是:为什么您觉得不需要/不想使用异步?当您想要创建可扩展的应用程序时,您需要这样做这是一个Web应用程序
只需让异步传播,并在2018年开始使用,也可以使用ConfigureAwait(false),其中可能的异步并不意味着并行。异步执行将有价值的线程池线程从对外部资源的阻塞中释放出来,而不会带来复杂性或性能成本。这意味着同一台IIS机器可以处理更多的并发请求,也就是说,它的可扩展性更高,通常是Task.Run(GetDataAsync)。结果可能就是您想要的结果。它会一直等到异步调用完成。那么,您是否会阻塞异步代码,从而导致死锁?这里真正的问题是:为什么您觉得不需要/不想使用异步?当您想要创建可扩展的应用程序时,您需要这样做这是一个Web应用程序
只需让异步传播,并在2018年开始使用,也可以使用ConfigureAwait(false),其中可能的异步并不意味着并行。异步执行将有价值的线程池线程从对外部资源的阻塞中释放出来,而不会带来复杂性或性能成本。这意味着同一台IIS机器可以处理更多的并发请求,也就是说,它的可扩展性更强。这将阻止整个线程池线程。据我所知,任务内部的阻塞具有未定义的行为。还有一件事,这个“响应”实际上是一个任务,因为您没有等待它,所以它甚至不会编译。@FCin从线程池中阻塞一个线程是可以的,我专门为此使用该线程。谢谢你的第二条评论-我更正了代码。如果你多次调用这个方法是不好的。每次它都会安排另一个线程池线程,导致它完全阻塞线程池并使应用程序暂时无响应。同时调用.Result
而不调用configurewait
将使asp.net应用程序死锁,因为任务将等待SynchronizationContext(UI)线程释放,但它永远不会空闲,因为它将等待任务完成。@FCin我的代码一次不会使用线程池中的多个线程。我不明白你说的“阻止线程池”是什么意思。这将阻止整个线程池线程。据我所知,任务内部的阻塞具有未定义的行为。还有一件事,这个“响应”实际上是一个任务,因为您没有等待它,所以它甚至不会编译。@FCin从线程池中阻塞一个线程是可以的,我专门为此使用该线程。谢谢你的第二条评论-我纠正了错误